Core/Inc/spi.h
New file @@ -0,0 +1,52 @@ /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file spi.h * @brief This file contains all the function prototypes for * the spi.c file ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __SPI_H__ #define __SPI_H__ #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "main.h" /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ extern SPI_HandleTypeDef hspi1; /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ void MX_SPI1_Init(void); /* USER CODE BEGIN Prototypes */ /* USER CODE END Prototypes */ #ifdef __cplusplus } #endif #endif /* __SPI_H__ */ Core/Inc/stm32l4xx_hal_conf.h
@@ -74,7 +74,7 @@ /*#define HAL_SD_MODULE_ENABLED */ /*#define HAL_SMBUS_MODULE_ENABLED */ /*#define HAL_SMARTCARD_MODULE_ENABLED */ /*#define HAL_SPI_MODULE_ENABLED */ #define HAL_SPI_MODULE_ENABLED /*#define HAL_SRAM_MODULE_ENABLED */ /*#define HAL_SWPMI_MODULE_ENABLED */ #define HAL_TIM_MODULE_ENABLED Core/Src/board/w25q.c
New file @@ -0,0 +1,638 @@ /********************************************************************** * Copyright: (C)2024 LingYun IoT System Studio * Author: GuoWenxue<guowenxue@gmail.com> * * Description: Winbond W25Q32 SPI norflash compatible driver on ISKBoard * Reference datasheet: <<W25Q256JV.pdf>> * * ChangeLog: * Version Date Author Description * V1.0.0 2024.08.29 GuoWenxue Release initial version * ***********************************************************************/ #include <stdio.h> #include <string.h> #include "main.h" #include "w25q.h" #include "spi.h" #define CONFIG_DEBUG_W25Q /* Enable W25Q norflash debug */ #ifdef CONFIG_DEBUG_W25Q #define spinor_print(format,args...) printf(format, ##args) #else #define spinor_print(format,args...) do{} while(0) #endif __attribute__((unused)) static void dump_buf(const char *prompt, uint8_t *buf, uint32_t size) { int i; if(!buf) return ; if(prompt) printf("%s\r\n", prompt); for(i=0; i<size; i++) printf("%02x ", buf[i]); printf("\r\n"); } #ifdef USE_FREERTOS #include "cmsis_os.h" #define mdelay(ms) osDelay(ms) #else #define mdelay(ms) HAL_Delay(ms) #endif /*+-----------------------+ *| SPI API Functions | *+-----------------------+*/ #define W25Q_SPI &hspi1 #define W25Q_CS_PORT GPIOA #define W25Q_CS_PIN GPIO_PIN_4 #define SPI_DUMMY_BYTE 0xA5 void spinor_gpio_init(struct spi_info *spi) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Initial W25Q Norflash SPI CS pin */ HAL_GPIO_WritePin(spi->cs_gpio, spi->cs_pin, GPIO_PIN_SET); GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Pin = spi->cs_pin; HAL_GPIO_Init(spi->cs_gpio, &GPIO_InitStruct); } void spi_cs_enable(struct spi_info *spi) { HAL_GPIO_WritePin(spi->cs_gpio, spi->cs_pin, GPIO_PIN_RESET); } void spi_cs_disable(struct spi_info *spi) { HAL_GPIO_WritePin(spi->cs_gpio, spi->cs_pin, GPIO_PIN_SET); } uint8_t spi_xfer(struct spi_info *spi, uint8_t data) { uint8_t rxbyte; HAL_SPI_TransmitReceive(spi->hspi, &data, &rxbyte, 1, 100); return rxbyte; } void spi_send(struct spi_info *spi, uint8_t *data, uint32_t bytes) { HAL_SPI_Transmit(spi->hspi, data, bytes, 100); } void spi_recv(struct spi_info *spi, uint8_t *buf, uint32_t size) { HAL_SPI_Receive(spi->hspi, buf, size, 100); } #define SPI_INFO(_hspi, _cs_gpio, _cs_pin) {\ .hspi = _hspi, \ .cs_gpio = _cs_gpio, \ .cs_pin = _cs_pin, \ .select = spi_cs_enable, \ .deselect = spi_cs_disable, \ .xfer = spi_xfer, \ .send = spi_send, \ .recv = spi_recv, \ } static struct spi_info spinor_spi = SPI_INFO(W25Q_SPI, W25Q_CS_PORT, W25Q_CS_PIN); /*+-----------------------+ *| W25Q SPI Norflash ID | *+-----------------------+*/ #define W25Q_PAGSIZE 256 /* 1Page=256B */ #define W25Q_SECSIZE 4096 /* 1Sector=16Pages=4KB */ #define W25Q_BLKSIZE 65536 /* 1Block=16Sector=64KB */ #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) /* JEDEC ID the 3rd bytes is the storage capacity */ #pragma GCC diagnostic ignored "-Wshift-count-overflow" #define CAPCITY_ID(id) (1UL<<(id&0xFF)) #define NOR_INFO(_name, _jedec_id) \ .name = _name, \ .jedec_id = _jedec_id, \ .block_size = W25Q_BLKSIZE, \ .sector_size= W25Q_SECSIZE, \ .page_size = W25Q_PAGSIZE, \ .capacity = CAPCITY_ID(_jedec_id), \ .n_blocks = CAPCITY_ID(_jedec_id)/W25Q_BLKSIZE, \ .n_sectors = CAPCITY_ID(_jedec_id)/W25Q_SECSIZE, \ .n_pages = CAPCITY_ID(_jedec_id)/W25Q_PAGSIZE, \ static struct flash_info spinor_ids[] = { { NOR_INFO("W25Q512", 0xef4020) }, { NOR_INFO("W25Q256", 0xef4019) }, { NOR_INFO("W25Q128", 0xef4018) }, { NOR_INFO("W25Q64", 0xef4017) }, { NOR_INFO("W25Q32", 0xef4016) }, { NOR_INFO("W25Q16", 0xef4015) }, { NOR_INFO("W25Q80", 0xef4014) }, { NOR_INFO("W25Q40", 0xef4013) }, { NOR_INFO("W25Q20", 0xef4012) }, { NOR_INFO("W25Q10", 0xef4011) }, }; /*+-------------------------------+ *| SPI Norflash HighLevel API | *+-------------------------------+*/ /* SPI Norflash API test function */ void spinor_test(void) { spinor_info_t spinor; int i; uint8_t buf[W25Q_PAGSIZE*2]; if( spinor_init(&spinor) < 0 ) return ; //spinor_erase_chip(&spinor); //spinor_erase_block(&spinor, 1, W25Q_BLKSIZE); spinor_erase_sector(&spinor, 1, W25Q_SECSIZE); memset(buf, 0, sizeof(buf)); spinor_read(&spinor, 0, buf, sizeof(buf)); dump_buf("<<<Read data after erase:\n", buf, sizeof(buf)); /* Read/Write data test on address not page align */ for(i=0; i<sizeof(buf); i++) buf[i] = i; spinor_write(&spinor, 8, buf, W25Q_PAGSIZE); memset(buf, 0, sizeof(buf)); spinor_read(&spinor, 0, buf, sizeof(buf)); dump_buf("<<<Read data after write:\n", buf, sizeof(buf)); return ; } /* Initial SPI and detect the flash chip. */ int spinor_init(struct spinor_info *spinor) { spinor->spi = &spinor_spi; spinor_gpio_init(spinor->spi); if( !spinor_detect_by_jedec(spinor) ) return -1; printf("Norflash %s detected, capacity %lu KB, %lu blocks, %lu sectors, %lu pages.\r\n", spinor->flash->name, spinor->flash->capacity>>10, spinor->flash->n_blocks, spinor->flash->n_sectors, spinor->flash->n_pages); return 0; } /* Description: Erase whole flash chip. * Reference : P60, 8.2.32 Chip Erase (C7h / 60h) */ int spinor_erase_chip(struct spinor_info *spinor) { struct spi_info *spi = spinor->spi; while (spinor->lock == 1) mdelay(1); spinor->lock = 1; #ifdef CONFIG_DEBUG_W25Q uint32_t StartTime = HAL_GetTick(); printf("Norflash EraseChip Begin...\r\n"); #endif spinor_write_enable(spi); spi->select(spi); spi->xfer(spi, SPINOR_OP_CHIP_ERASE); spi->deselect(spi); spinor_WaitForWriteEnd(spi); #ifdef CONFIG_DEBUG_W25Q printf("Norflash EraseChip done after %ld ms!\r\n", HAL_GetTick() - StartTime); #endif mdelay(10); spinor->lock = 0; return 0; } /* Description: Erase blocks by 64KiB, * Reference : P59, 8.2.31 64KB Block Erase with 4-Byte Address (DCh) * @address is the erase start physical address, which can be not block alignment such as 0x10001. * @size is the erase size, which can be larger than a block such as 4097, and it will erase 2 blocks; */ int spinor_erase_block(struct spinor_info *spinor, uint32_t address, uint32_t size) { struct spi_info *spi = spinor->spi; struct flash_info *flash = spinor->flash; uint32_t block, first, last; uint32_t addr; while (spinor->lock == 1) mdelay(1); spinor->lock = 1; /* find first and last erase block */ first = address / flash->block_size; last = (address+size-1) / flash->block_size; #ifdef CONFIG_DEBUG_W25Q printf("Norflash Erase %ld Bytes Block@0x%lx Begin...\r\n", size, address); uint32_t StartTime = HAL_GetTick(); #endif /* start erase all the blocks */ for( block=first; block<=last; block++) { addr = block * flash->sector_size; #ifdef CONFIG_DEBUG_W25Q printf("Norflash Erase Block@%lx ...\r\n", addr); #endif spinor_WaitForWriteEnd(spi); spinor_write_enable(spi); spi->select(spi); if (spinor->flash->n_blocks >= 512 ) /* larger than W25Q256 */ { spi->xfer(spi, SPINOR_OP_BE_4K_4B); spi->xfer(spi, (addr & 0xFF000000) >> 24); } else { spi->xfer(spi, SPINOR_OP_BE_4K); } spi->xfer(spi, (addr & 0xFF0000) >> 16); spi->xfer(spi, (addr & 0xFF00) >> 8); spi->xfer(spi, addr & 0xFF); spi->deselect(spi); spinor_WaitForWriteEnd(spi); } #ifdef CONFIG_DEBUG_W25Q printf("Norflash EraseBlock@0x%lx done after %ld ms\r\n", address, HAL_GetTick() - StartTime); mdelay(100); #endif mdelay(1); spinor->lock = 0; return 0; } /* Description: Erase sectors by 4KiB * Reference : P56, 8.2.28 Sector Erase with 4-Byte Address (21h) * @address is the erase start physical address, which can be not sector alignment such as 0x1001. * @size is the erase size, which can be larger than a sector such as 4097, and it will erase 2 sectors; */ int spinor_erase_sector(struct spinor_info *spinor, uint32_t address, uint32_t size) { struct spi_info *spi = spinor->spi; struct flash_info *flash = spinor->flash; uint32_t sector, first, last; uint32_t addr; while (spinor->lock == 1) mdelay(1); spinor->lock = 1; /* find first and last erase sector */ first = address / flash->sector_size; last = (address+size-1) / flash->sector_size; #ifdef CONFIG_DEBUG_W25Q uint32_t StartTime = HAL_GetTick(); printf("Norflash Erase %ld Bytes Sector@0x%lx Begin...\r\n", size, address); #endif /* start erase all the sectors */ for( sector=first; sector<=last; sector++) { addr = sector * flash->sector_size; #ifdef CONFIG_DEBUG_W25Q printf("Norflash Erase Sector@%lx ...\r\n", addr); #endif spinor_WaitForWriteEnd(spi); spinor_write_enable(spi); spi->select(spi); if (spinor->flash->n_blocks >= 512 ) /* larger than W25Q256 */ { spi->xfer(spi, SPINOR_OP_SE_4B); spi->xfer(spi, (addr & 0xFF000000) >> 24); } else { spi->xfer(spi, SPINOR_OP_SE); } spi->xfer(spi, (addr & 0xFF0000) >> 16); spi->xfer(spi, (addr & 0xFF00) >> 8); spi->xfer(spi, addr & 0xFF); spi->deselect(spi); spinor_WaitForWriteEnd(spi); } #ifdef CONFIG_DEBUG_W25Q printf("Norflash EraseSector@0x%lx done after %ld ms\r\n", address, HAL_GetTick() - StartTime); #endif mdelay(1); spinor->lock = 0; return 0; } /* P32: 10.2.14 Page Program (02h) */ int spinor_write(struct spinor_info *spinor, uint32_t address, uint8_t *data, uint32_t bytes) { struct spi_info *spi = spinor->spi; struct flash_info *flash = spinor->flash; uint32_t page, first, last; uint32_t addr, ofset, len; while (spinor->lock == 1) mdelay(1); spinor->lock = 1; /* find first and last write page */ first = address / flash->page_size; last = (address+bytes-1) / flash->page_size; #ifdef CONFIG_DEBUG_W25Q uint32_t StartTime = HAL_GetTick(); printf("Norflash Write %ld Bytes to addr@0x%lx Begin...\r\n", bytes, address); #endif /* address in page and offset in buffer */ addr = address; ofset = 0; /* start write all the pages */ for( page=first; page<=last; page++) { len = flash->page_size - (addr%flash->page_size); len = len > bytes ? bytes : len; #ifdef CONFIG_DEBUG_W25Q printf("Norflash write addr@0x%lx, %lu bytes\r\n", addr, len); #endif spinor_WaitForWriteEnd(spi); spinor_write_enable(spi); spi->select(spi); if (spinor->flash->n_blocks >= 512 ) { spi->xfer(spi, SPINOR_OP_PP_4B); spi->xfer(spi, (addr & 0xFF000000) >> 24); } else { spi->xfer(spi, SPINOR_OP_PP); } spi->xfer(spi, (addr & 0xFF0000) >> 16); spi->xfer(spi, (addr & 0xFF00) >> 8); spi->xfer(spi, addr & 0xFF); /* send data */ spi->send(spi, data+ofset, len); spi->deselect(spi); spinor_WaitForWriteEnd(spi); addr += len; ofset += len; bytes -= len; } #ifdef CONFIG_DEBUG_W25Q printf("Norflash WriteByte@0x%lx done after %ld ms\r\n", address, HAL_GetTick() - StartTime); #endif mdelay(1); spinor->lock = 0; return 0; } /* Description: The Fast Read instruction can read the entire memory chip. * Reference : P41, 8.2.13 Fast Read with 4-Byte Address (0Ch) * @address is the read start physical address, which can be not page alignment such as 0x101. * @size is the read size, which can be larger than a page such as 257, and it will read 2 pages; */ int spinor_read(struct spinor_info *spinor, uint32_t address, uint8_t *buf, uint32_t bytes) { struct spi_info *spi = spinor->spi; while (spinor->lock == 1) mdelay(1); spinor->lock = 1; #ifdef CONFIG_DEBUG_W25Q uint32_t StartTime = HAL_GetTick(); printf("Norflash Read %ld Bytes from addr@0x%lx Begin...\r\n", bytes, address); #endif spi->select(spi); /* send instruction and address */ if (spinor->flash->n_blocks >= 512 ) { spi->xfer(spi, SPINOR_OP_READ_FAST_4B); spi->xfer(spi, (address & 0xFF000000) >> 24); } else { spi->xfer(spi, SPINOR_OP_READ_FAST); } spi->xfer(spi, (address & 0xFF0000) >> 16); spi->xfer(spi, (address & 0xFF00) >> 8); spi->xfer(spi, address & 0xFF); /* read data */ spi->xfer(spi, SPI_DUMMY_BYTE); spi->recv(spi, buf, bytes); spi->deselect(spi); #ifdef CONFIG_DEBUG_W25Q printf("Norflash ReadBytes@0x%lx done after %ld ms\r\n", address, HAL_GetTick() - StartTime); #endif spinor->lock = 0; return 0; } /*+-------------------------------+ *| SPI Norflash LowLevel API | *+-------------------------------+*/ /* Detect the norflash by JEDEC ID */ int spinor_detect_by_jedec(struct spinor_info *spinor) { uint32_t jedec_id; int i, found = 0; jedec_id = spinor_read_jedecid(spinor->spi); for(i=0; i<ARRAY_SIZE(spinor_ids); i++) { if(spinor_ids[i].jedec_id == jedec_id) { found = 1; spinor->flash = &spinor_ids[i]; break; } } printf("Detect JEDEC ID[0x%lx], Norflash %s found\r\n", jedec_id, found?spinor->flash->name:"not"); return found; } /* Description: Read the chipset UNIQUE ID. * Reference : P68, 8.2.40 Read Unique ID Number (4Bh) */ int spinor_read_uniqid(struct spi_info *spi, uint8_t *uniq_id) { uint8_t i; uint8_t id; if( !uniq_id ) return -1; spi->select(spi); spi->xfer(spi, SPINOR_OP_RDUID); /* Skip 4 bytes dummy bytes */ for (i=0; i<4; i++) spi->xfer(spi, SPI_DUMMY_BYTE); for (i=0; i<8; i++) { id = spi->xfer(spi, SPI_DUMMY_BYTE); uniq_id[i] = id; } spi->deselect(spi); return 0; } /* Description: Read the chipset JEDEC ID. * Reference : P69, 8.2.41 Read JEDEC ID (9Fh) */ uint32_t spinor_read_jedecid(struct spi_info *spi) { uint32_t jedec_id = 0x0; uint8_t id[3]; spi->select(spi); spi->xfer(spi, SPINOR_OP_RDID); id[0] = spi->xfer(spi, SPI_DUMMY_BYTE); /* Vendor ID */ id[1] = spi->xfer(spi, SPI_DUMMY_BYTE); /* Memory Type */ id[2] = spi->xfer(spi, SPI_DUMMY_BYTE); /* Storage Capacity */ spi->deselect(spi); jedec_id = (id[0] << 16) | (id[1] << 8) | id[2]; return jedec_id; } /* Description: Write Enable * Reference : P31, 8.2.1 Write Enable (06h) */ void spinor_write_enable(struct spi_info *spi) { spi->select(spi); spi->xfer(spi, SPINOR_OP_WREN); spi->deselect(spi); mdelay(1); } /* Description: Write Disable * Reference : P32, 8.2.3 Write Disable (04h) */ void spinor_write_disable(struct spi_info *spi) { spi->select(spi); spi->xfer(spi, SPINOR_OP_WRDI); spi->deselect(spi); mdelay(1); } /* Description: Read Status Register * Reference : P32, 8.2.4 Read Status Register-1 (05h), Status Register-2 (35h) & Status Register-3 (15h) */ uint8_t spinor_read_status_reg(struct spi_info *spi, uint8_t reg) { uint8_t value = 0; uint8_t cmd[REG_STATUS_MAX] = { SPINOR_OP_RDSR1 , SPINOR_OP_RDSR2, SPINOR_OP_RDSR3 }; /* Status Register 1~3 */ if( reg>= REG_STATUS_MAX ) return 0xFF; spi->select(spi); spi->xfer(spi, cmd[reg]); value = spi->xfer(spi, SPI_DUMMY_BYTE); spi->deselect(spi); return value; } /* Description: Write Status Register * Reference : P33, 8.2.5 Write Status Register-1 (01h), Status Register-2 (31h) & Status Register-3 (11h) */ void spinor_write_status_reg(struct spi_info *spi, uint8_t reg, uint8_t value) { uint8_t cmd[REG_STATUS_MAX] = { SPINOR_OP_WRSR1 , SPINOR_OP_WRSR2, SPINOR_OP_WRSR3 }; /* Status Register 1~3 */ if( reg>= REG_STATUS_MAX ) return ; spi->select(spi); spi->xfer(spi, cmd[reg]); value = spi->xfer(spi, value); spi->deselect(spi); } /* Description: Wait flash program/erase finished by read Status Register for BUSY bit * Reference : P15, 7.1 Status Registers */ void spinor_WaitForWriteEnd(struct spi_info *spi) { uint8_t value = 0; mdelay(1); spi->select(spi); spi->xfer(spi, SPINOR_OP_RDSR1); do { value = spi->xfer(spi, SPI_DUMMY_BYTE); mdelay(1); } while ((value & 0x01) == 0x01); spi->deselect(spi); } Core/Src/board/w25q.h
New file @@ -0,0 +1,174 @@ /********************************************************************** * Copyright: (C)2024 LingYun IoT System Studio * Author: GuoWenxue<guowenxue@gmail.com> * * Description: Winbond W25Q32 SPI norflash compatible driver on ISKBoard * Reference datasheet: <<W25Q256JV.pdf>> * * ChangeLog: * Version Date Author Description * V1.0.0 2024.08.29 GuoWenxue Release initial version * ***********************************************************************/ #ifndef __W25Q_H_ #define __W25Q_H_ #include <sys/types.h> #include <stdint.h> /* Flash opcodes. Refer to <<W25Q256JV.pdf>> P26 Table 8.1.2 Instruction Set Table */ #define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ #define SPINOR_OP_RDUID 0x4b /* Read unique ID */ #define SPINOR_OP_WRSR1 0x01 /* Write status register-1 */ #define SPINOR_OP_WRSR2 0x31 /* Write status register-2 */ #define SPINOR_OP_WRSR3 0x11 /* Write status register-3 */ #define SPINOR_OP_BP 0x02 /* Byte program */ #define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */ #define SPINOR_OP_WRDI 0x04 /* Write disable */ #define SPINOR_OP_RDSR1 0x05 /* Read status register-1 */ #define SPINOR_OP_RDSR2 0x35 /* Read status register-2 */ #define SPINOR_OP_RDSR3 0x15 /* Read status register-3 */ #define SPINOR_OP_WREN 0x06 /* Write enable */ #define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */ #define SPINOR_OP_READ_FAST_4B 0x0c /* Read data bytes (high frequency) */ #define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */ #define SPINOR_OP_BE_4K_4B 0xdc /* Block erase (64KiB) with 4-Byte Address */ #define SPINOR_OP_BE_4K 0xd8 /* Block erase (64KiB) */ #define SPINOR_OP_SE_4B 0x21 /* Sector erase (4KiB) with 4-Byte Address */ #define SPINOR_OP_SE 0x20 /* Sector erase (4KiB) */ #define SPINOR_OP_PP_4B 0x12 /* Page Program (up to 256 bytes) with 4-Byte Address */ #define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ #define SPINOR_OP_SRSTEN 0x66 /* Software Reset Enable */ #define SPINOR_OP_SRST 0x99 /* Software Reset */ typedef struct spi_info { SPI_HandleTypeDef *hspi; /* SPI port */ GPIO_TypeDef *cs_gpio; /* CS GPIO group */ uint16_t cs_pin; /* CS GPIO pin */ void (*select)(struct spi_info *spi); /* CS enable function */ void (*deselect)(struct spi_info *spi); /* CS disable function */ uint8_t (*xfer)(struct spi_info *spi, uint8_t data); /* Transmit and Receive one byte */ void (*send)(struct spi_info *spi, uint8_t *data, uint32_t bytes); /* Transmit $bytes data */ void (*recv)(struct spi_info *spi, uint8_t *buf, uint32_t size); /* Receive $size data */ } spi_info_t; typedef struct flash_info { char *name; /* Chip name */ uint32_t jedec_id; /* JEDEC ID, 3 bytes */ uint32_t capacity; /* Chip size in bytes */ uint32_t block_size; /* Block size in bytes */ uint32_t sector_size; /* Sector size in bytes */ uint32_t page_size; /* Page size in bytes */ uint32_t n_blocks; /* Number of blocks */ uint32_t n_sectors; /* Number of sectors */ uint32_t n_pages; /* Number of pages */ } flash_info_t; typedef struct spinor_info { spi_info_t *spi; flash_info_t *flash; uint8_t lock; } spinor_info_t; /* Status registers */ enum { REG_STATUS1, REG_STATUS2, REG_STATUS3, REG_STATUS_MAX, }; /*+-------------------------------+ *| SPI Norflash HighLevel API | *+-------------------------------+*/ /* SPI Norflash API test function */ extern void spinor_test(void); /* Initial SPI and detect the flash chip */ extern int spinor_init(struct spinor_info *spinor); /* Description: Erase whole flash chip. * Reference : P60, 8.2.32 Chip Erase (C7h / 60h) */ extern int spinor_erase_chip(struct spinor_info *spinor); /* Description: Erase blocks by 64KiB, * Reference : P59, 8.2.31 64KB Block Erase with 4-Byte Address (DCh) * @address is the erase start physical address, which can be not block alignment such as 0x10001. * @size is the erase size, which can be larger than a block such as 4097, and it will erase 2 blocks; */ extern int spinor_erase_block(struct spinor_info *spinor, uint32_t address, uint32_t size); /* Description: Erase sectors by 4KiB * Reference : P56, 8.2.28 Sector Erase with 4-Byte Address (21h) * @address is the erase start physical address, which can be not sector alignment such as 0x1001. * @size is the erase size, which can be larger than a sector such as 4097, and it will erase 2 sectors; */ extern int spinor_erase_sector(struct spinor_info *spinor, uint32_t address, uint32_t size); /* Description: Page random write by 256B * @addr is the write start physical address, which can be not page alignment such as 0x101. * @size is the write size, which can be larger than a page such as 257, and it will write 2 pages; */ extern int spinor_write(struct spinor_info *spinor, uint32_t address, uint8_t *data, uint32_t bytes); /* Description: The Fast Read instruction can read the entire memory chip. * Reference : P41, 8.2.13 Fast Read with 4-Byte Address (0Ch) * @address is the read start physical address, which can be not page alignment such as 0x101. * @size is the read size, which can be larger than a page such as 257, and it will read 2 pages; */ extern int spinor_read(struct spinor_info *spinor, uint32_t address, uint8_t *buf, uint32_t bytes); /*+-------------------------------+ *| SPI Norflash LowLevel API | *+-------------------------------+*/ /* Detect the norflash by JEDEC ID */ int spinor_detect_by_jedec(struct spinor_info *spinor); /* Description: Read the chipset UNIQUE ID. * Reference : P68, 8.2.40 Read Unique ID Number (4Bh) */ int spinor_read_uniqid(struct spi_info *spi, uint8_t *uniq_id); /* Description: Read the chipset JEDEC ID. * Reference : P69, 8.2.41 Read JEDEC ID (9Fh) */ uint32_t spinor_read_jedecid(struct spi_info *spi); /* Description: Write Enable * Reference : P31, 8.2.1 Write Enable (06h) */ void spinor_write_enable(struct spi_info *spi); /* Description: Write Disable * Reference : P32, 8.2.3 Write Disable (04h) */ void spinor_write_disable(struct spi_info *spi); /* Description: Read Status Register * Reference : P32, 8.2.4 Read Status Register-1 (05h), Status Register-2 (35h) & Status Register-3 (15h) */ uint8_t spinor_read_status_reg(struct spi_info *spi, uint8_t reg); /* Description: Write Status Register * Reference : P33, 8.2.5 Write Status Register-1 (01h), Status Register-2 (31h) & Status Register-3 (11h) */ void spinor_write_status_reg(struct spi_info *spi, uint8_t reg, uint8_t value); /* Description: Wait flash program/erase finished by read Status Register for BUSY bit * Reference : P15, 7.1 Status Registers */ void spinor_WaitForWriteEnd(struct spi_info *spi); #endif Core/Src/gpio.c
@@ -46,9 +46,9 @@ /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /*Configure GPIO pin Output Level */ Core/Src/main.c
@@ -19,6 +19,7 @@ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "adc.h" #include "spi.h" #include "tim.h" #include "usart.h" #include "gpio.h" @@ -27,6 +28,7 @@ /* USER CODE BEGIN Includes */ #include "miscdev.h" #include "sht20.h" #include "w25q.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -95,8 +97,13 @@ MX_ADC1_Init(); MX_TIM6_Init(); MX_TIM1_Init(); MX_SPI1_Init(); /* USER CODE BEGIN 2 */ beep_start(2, 300); spinor_test(); do {} while(1); /* USER CODE END 2 */ /* Infinite loop */ Core/Src/spi.c
New file @@ -0,0 +1,121 @@ /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file spi.c * @brief This file provides code for the configuration * of the SPI instances. ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "spi.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ SPI_HandleTypeDef hspi1; /* SPI1 init function */ void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ /* USER CODE END SPI1_Init 0 */ /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ } void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(spiHandle->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspInit 0 */ /* USER CODE END SPI1_MspInit 0 */ /* SPI1 clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */ } } void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle) { if(spiHandle->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspDeInit 0 */ /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); /* USER CODE BEGIN SPI1_MspDeInit 1 */ /* USER CODE END SPI1_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_spi.h
New file @@ -0,0 +1,855 @@ /** ****************************************************************************** * @file stm32l4xx_hal_spi.h * @author MCD Application Team * @brief Header file of SPI HAL module. ****************************************************************************** * @attention * * Copyright (c) 2017 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef STM32L4xx_HAL_SPI_H #define STM32L4xx_HAL_SPI_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "stm32l4xx_hal_def.h" /** @addtogroup STM32L4xx_HAL_Driver * @{ */ /** @addtogroup SPI * @{ */ /* Exported types ------------------------------------------------------------*/ /** @defgroup SPI_Exported_Types SPI Exported Types * @{ */ /** * @brief SPI Configuration Structure definition */ typedef struct { uint32_t Mode; /*!< Specifies the SPI operating mode. This parameter can be a value of @ref SPI_Mode */ uint32_t Direction; /*!< Specifies the SPI bidirectional mode state. This parameter can be a value of @ref SPI_Direction */ uint32_t DataSize; /*!< Specifies the SPI data size. This parameter can be a value of @ref SPI_Data_Size */ uint32_t CLKPolarity; /*!< Specifies the serial clock steady state. This parameter can be a value of @ref SPI_Clock_Polarity */ uint32_t CLKPhase; /*!< Specifies the clock active edge for the bit capture. This parameter can be a value of @ref SPI_Clock_Phase */ uint32_t NSS; /*!< Specifies whether the NSS signal is managed by hardware (NSS pin) or by software using the SSI bit. This parameter can be a value of @ref SPI_Slave_Select_management */ uint32_t BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be used to configure the transmit and receive SCK clock. This parameter can be a value of @ref SPI_BaudRate_Prescaler @note The communication clock is derived from the master clock. The slave clock does not need to be set. */ uint32_t FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit. This parameter can be a value of @ref SPI_MSB_LSB_transmission */ uint32_t TIMode; /*!< Specifies if the TI mode is enabled or not. This parameter can be a value of @ref SPI_TI_mode */ uint32_t CRCCalculation; /*!< Specifies if the CRC calculation is enabled or not. This parameter can be a value of @ref SPI_CRC_Calculation */ uint32_t CRCPolynomial; /*!< Specifies the polynomial used for the CRC calculation. This parameter must be an odd number between Min_Data = 1 and Max_Data = 65535 */ uint32_t CRCLength; /*!< Specifies the CRC Length used for the CRC calculation. CRC Length is only used with Data8 and Data16, not other data size This parameter can be a value of @ref SPI_CRC_length */ uint32_t NSSPMode; /*!< Specifies whether the NSSP signal is enabled or not . This parameter can be a value of @ref SPI_NSSP_Mode This mode is activated by the NSSP bit in the SPIx_CR2 register and it takes effect only if the SPI interface is configured as Motorola SPI master (FRF=0) with capture on the first edge (SPIx_CR1 CPHA = 0, CPOL setting is ignored).. */ } SPI_InitTypeDef; /** * @brief HAL SPI State structure definition */ typedef enum { HAL_SPI_STATE_RESET = 0x00U, /*!< Peripheral not Initialized */ HAL_SPI_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */ HAL_SPI_STATE_BUSY = 0x02U, /*!< an internal process is ongoing */ HAL_SPI_STATE_BUSY_TX = 0x03U, /*!< Data Transmission process is ongoing */ HAL_SPI_STATE_BUSY_RX = 0x04U, /*!< Data Reception process is ongoing */ HAL_SPI_STATE_BUSY_TX_RX = 0x05U, /*!< Data Transmission and Reception process is ongoing */ HAL_SPI_STATE_ERROR = 0x06U, /*!< SPI error state */ HAL_SPI_STATE_ABORT = 0x07U /*!< SPI abort is ongoing */ } HAL_SPI_StateTypeDef; /** * @brief SPI handle Structure definition */ typedef struct __SPI_HandleTypeDef { SPI_TypeDef *Instance; /*!< SPI registers base address */ SPI_InitTypeDef Init; /*!< SPI communication parameters */ const uint8_t *pTxBuffPtr; /*!< Pointer to SPI Tx transfer Buffer */ uint16_t TxXferSize; /*!< SPI Tx Transfer size */ __IO uint16_t TxXferCount; /*!< SPI Tx Transfer Counter */ uint8_t *pRxBuffPtr; /*!< Pointer to SPI Rx transfer Buffer */ uint16_t RxXferSize; /*!< SPI Rx Transfer size */ __IO uint16_t RxXferCount; /*!< SPI Rx Transfer Counter */ uint32_t CRCSize; /*!< SPI CRC size used for the transfer */ void (*RxISR)(struct __SPI_HandleTypeDef *hspi); /*!< function pointer on Rx ISR */ void (*TxISR)(struct __SPI_HandleTypeDef *hspi); /*!< function pointer on Tx ISR */ DMA_HandleTypeDef *hdmatx; /*!< SPI Tx DMA Handle parameters */ DMA_HandleTypeDef *hdmarx; /*!< SPI Rx DMA Handle parameters */ HAL_LockTypeDef Lock; /*!< Locking object */ __IO HAL_SPI_StateTypeDef State; /*!< SPI communication state */ __IO uint32_t ErrorCode; /*!< SPI Error code */ #if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) void (* TxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Tx Completed callback */ void (* RxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Rx Completed callback */ void (* TxRxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI TxRx Completed callback */ void (* TxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Tx Half Completed callback */ void (* RxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Rx Half Completed callback */ void (* TxRxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI TxRx Half Completed callback */ void (* ErrorCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Error callback */ void (* AbortCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Abort callback */ void (* MspInitCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Msp Init callback */ void (* MspDeInitCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Msp DeInit callback */ #endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ } SPI_HandleTypeDef; #if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) /** * @brief HAL SPI Callback ID enumeration definition */ typedef enum { HAL_SPI_TX_COMPLETE_CB_ID = 0x00U, /*!< SPI Tx Completed callback ID */ HAL_SPI_RX_COMPLETE_CB_ID = 0x01U, /*!< SPI Rx Completed callback ID */ HAL_SPI_TX_RX_COMPLETE_CB_ID = 0x02U, /*!< SPI TxRx Completed callback ID */ HAL_SPI_TX_HALF_COMPLETE_CB_ID = 0x03U, /*!< SPI Tx Half Completed callback ID */ HAL_SPI_RX_HALF_COMPLETE_CB_ID = 0x04U, /*!< SPI Rx Half Completed callback ID */ HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID = 0x05U, /*!< SPI TxRx Half Completed callback ID */ HAL_SPI_ERROR_CB_ID = 0x06U, /*!< SPI Error callback ID */ HAL_SPI_ABORT_CB_ID = 0x07U, /*!< SPI Abort callback ID */ HAL_SPI_MSPINIT_CB_ID = 0x08U, /*!< SPI Msp Init callback ID */ HAL_SPI_MSPDEINIT_CB_ID = 0x09U /*!< SPI Msp DeInit callback ID */ } HAL_SPI_CallbackIDTypeDef; /** * @brief HAL SPI Callback pointer definition */ typedef void (*pSPI_CallbackTypeDef)(SPI_HandleTypeDef *hspi); /*!< pointer to an SPI callback function */ #endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ /** * @} */ /* Exported constants --------------------------------------------------------*/ /** @defgroup SPI_Exported_Constants SPI Exported Constants * @{ */ /** @defgroup SPI_Error_Code SPI Error Code * @{ */ #define HAL_SPI_ERROR_NONE (0x00000000U) /*!< No error */ #define HAL_SPI_ERROR_MODF (0x00000001U) /*!< MODF error */ #define HAL_SPI_ERROR_CRC (0x00000002U) /*!< CRC error */ #define HAL_SPI_ERROR_OVR (0x00000004U) /*!< OVR error */ #define HAL_SPI_ERROR_FRE (0x00000008U) /*!< FRE error */ #define HAL_SPI_ERROR_DMA (0x00000010U) /*!< DMA transfer error */ #define HAL_SPI_ERROR_FLAG (0x00000020U) /*!< Error on RXNE/TXE/BSY/FTLVL/FRLVL Flag */ #define HAL_SPI_ERROR_ABORT (0x00000040U) /*!< Error during SPI Abort procedure */ #if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) #define HAL_SPI_ERROR_INVALID_CALLBACK (0x00000080U) /*!< Invalid Callback error */ #endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ /** * @} */ /** @defgroup SPI_Mode SPI Mode * @{ */ #define SPI_MODE_SLAVE (0x00000000U) #define SPI_MODE_MASTER (SPI_CR1_MSTR | SPI_CR1_SSI) /** * @} */ /** @defgroup SPI_Direction SPI Direction Mode * @{ */ #define SPI_DIRECTION_2LINES (0x00000000U) #define SPI_DIRECTION_2LINES_RXONLY SPI_CR1_RXONLY #define SPI_DIRECTION_1LINE SPI_CR1_BIDIMODE /** * @} */ /** @defgroup SPI_Data_Size SPI Data Size * @{ */ #define SPI_DATASIZE_4BIT (0x00000300U) #define SPI_DATASIZE_5BIT (0x00000400U) #define SPI_DATASIZE_6BIT (0x00000500U) #define SPI_DATASIZE_7BIT (0x00000600U) #define SPI_DATASIZE_8BIT (0x00000700U) #define SPI_DATASIZE_9BIT (0x00000800U) #define SPI_DATASIZE_10BIT (0x00000900U) #define SPI_DATASIZE_11BIT (0x00000A00U) #define SPI_DATASIZE_12BIT (0x00000B00U) #define SPI_DATASIZE_13BIT (0x00000C00U) #define SPI_DATASIZE_14BIT (0x00000D00U) #define SPI_DATASIZE_15BIT (0x00000E00U) #define SPI_DATASIZE_16BIT (0x00000F00U) /** * @} */ /** @defgroup SPI_Clock_Polarity SPI Clock Polarity * @{ */ #define SPI_POLARITY_LOW (0x00000000U) #define SPI_POLARITY_HIGH SPI_CR1_CPOL /** * @} */ /** @defgroup SPI_Clock_Phase SPI Clock Phase * @{ */ #define SPI_PHASE_1EDGE (0x00000000U) #define SPI_PHASE_2EDGE SPI_CR1_CPHA /** * @} */ /** @defgroup SPI_Slave_Select_management SPI Slave Select Management * @{ */ #define SPI_NSS_SOFT SPI_CR1_SSM #define SPI_NSS_HARD_INPUT (0x00000000U) #define SPI_NSS_HARD_OUTPUT (SPI_CR2_SSOE << 16U) /** * @} */ /** @defgroup SPI_NSSP_Mode SPI NSS Pulse Mode * @{ */ #define SPI_NSS_PULSE_ENABLE SPI_CR2_NSSP #define SPI_NSS_PULSE_DISABLE (0x00000000U) /** * @} */ /** @defgroup SPI_BaudRate_Prescaler SPI BaudRate Prescaler * @{ */ #define SPI_BAUDRATEPRESCALER_2 (0x00000000U) #define SPI_BAUDRATEPRESCALER_4 (SPI_CR1_BR_0) #define SPI_BAUDRATEPRESCALER_8 (SPI_CR1_BR_1) #define SPI_BAUDRATEPRESCALER_16 (SPI_CR1_BR_1 | SPI_CR1_BR_0) #define SPI_BAUDRATEPRESCALER_32 (SPI_CR1_BR_2) #define SPI_BAUDRATEPRESCALER_64 (SPI_CR1_BR_2 | SPI_CR1_BR_0) #define SPI_BAUDRATEPRESCALER_128 (SPI_CR1_BR_2 | SPI_CR1_BR_1) #define SPI_BAUDRATEPRESCALER_256 (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) /** * @} */ /** @defgroup SPI_MSB_LSB_transmission SPI MSB LSB Transmission * @{ */ #define SPI_FIRSTBIT_MSB (0x00000000U) #define SPI_FIRSTBIT_LSB SPI_CR1_LSBFIRST /** * @} */ /** @defgroup SPI_TI_mode SPI TI Mode * @{ */ #define SPI_TIMODE_DISABLE (0x00000000U) #define SPI_TIMODE_ENABLE SPI_CR2_FRF /** * @} */ /** @defgroup SPI_CRC_Calculation SPI CRC Calculation * @{ */ #define SPI_CRCCALCULATION_DISABLE (0x00000000U) #define SPI_CRCCALCULATION_ENABLE SPI_CR1_CRCEN /** * @} */ /** @defgroup SPI_CRC_length SPI CRC Length * @{ * This parameter can be one of the following values: * SPI_CRC_LENGTH_DATASIZE: aligned with the data size * SPI_CRC_LENGTH_8BIT : CRC 8bit * SPI_CRC_LENGTH_16BIT : CRC 16bit */ #define SPI_CRC_LENGTH_DATASIZE (0x00000000U) #define SPI_CRC_LENGTH_8BIT (0x00000001U) #define SPI_CRC_LENGTH_16BIT (0x00000002U) /** * @} */ /** @defgroup SPI_FIFO_reception_threshold SPI FIFO Reception Threshold * @{ * This parameter can be one of the following values: * SPI_RXFIFO_THRESHOLD or SPI_RXFIFO_THRESHOLD_QF : * RXNE event is generated if the FIFO * level is greater or equal to 1/4(8-bits). * SPI_RXFIFO_THRESHOLD_HF: RXNE event is generated if the FIFO * level is greater or equal to 1/2(16 bits). */ #define SPI_RXFIFO_THRESHOLD SPI_CR2_FRXTH #define SPI_RXFIFO_THRESHOLD_QF SPI_CR2_FRXTH #define SPI_RXFIFO_THRESHOLD_HF (0x00000000U) /** * @} */ /** @defgroup SPI_Interrupt_definition SPI Interrupt Definition * @{ */ #define SPI_IT_TXE SPI_CR2_TXEIE #define SPI_IT_RXNE SPI_CR2_RXNEIE #define SPI_IT_ERR SPI_CR2_ERRIE /** * @} */ /** @defgroup SPI_Flags_definition SPI Flags Definition * @{ */ #define SPI_FLAG_RXNE SPI_SR_RXNE /* SPI status flag: Rx buffer not empty flag */ #define SPI_FLAG_TXE SPI_SR_TXE /* SPI status flag: Tx buffer empty flag */ #define SPI_FLAG_BSY SPI_SR_BSY /* SPI status flag: Busy flag */ #define SPI_FLAG_CRCERR SPI_SR_CRCERR /* SPI Error flag: CRC error flag */ #define SPI_FLAG_MODF SPI_SR_MODF /* SPI Error flag: Mode fault flag */ #define SPI_FLAG_OVR SPI_SR_OVR /* SPI Error flag: Overrun flag */ #define SPI_FLAG_FRE SPI_SR_FRE /* SPI Error flag: TI mode frame format error flag */ #define SPI_FLAG_FTLVL SPI_SR_FTLVL /* SPI fifo transmission level */ #define SPI_FLAG_FRLVL SPI_SR_FRLVL /* SPI fifo reception level */ #define SPI_FLAG_MASK (SPI_SR_RXNE | SPI_SR_TXE | SPI_SR_BSY | SPI_SR_CRCERR\ | SPI_SR_MODF | SPI_SR_OVR | SPI_SR_FRE | SPI_SR_FTLVL | SPI_SR_FRLVL) /** * @} */ /** @defgroup SPI_transmission_fifo_status_level SPI Transmission FIFO Status Level * @{ */ #define SPI_FTLVL_EMPTY (0x00000000U) #define SPI_FTLVL_QUARTER_FULL (0x00000800U) #define SPI_FTLVL_HALF_FULL (0x00001000U) #define SPI_FTLVL_FULL (0x00001800U) /** * @} */ /** @defgroup SPI_reception_fifo_status_level SPI Reception FIFO Status Level * @{ */ #define SPI_FRLVL_EMPTY (0x00000000U) #define SPI_FRLVL_QUARTER_FULL (0x00000200U) #define SPI_FRLVL_HALF_FULL (0x00000400U) #define SPI_FRLVL_FULL (0x00000600U) /** * @} */ /** * @} */ /* Exported macros -----------------------------------------------------------*/ /** @defgroup SPI_Exported_Macros SPI Exported Macros * @{ */ /** @brief Reset SPI handle state. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @retval None */ #if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) #define __HAL_SPI_RESET_HANDLE_STATE(__HANDLE__) \ do{ \ (__HANDLE__)->State = HAL_SPI_STATE_RESET; \ (__HANDLE__)->MspInitCallback = NULL; \ (__HANDLE__)->MspDeInitCallback = NULL; \ } while(0) #else #define __HAL_SPI_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SPI_STATE_RESET) #endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ /** @brief Enable the specified SPI interrupts. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @param __INTERRUPT__ specifies the interrupt source to enable. * This parameter can be one of the following values: * @arg SPI_IT_TXE: Tx buffer empty interrupt enable * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable * @arg SPI_IT_ERR: Error interrupt enable * @retval None */ #define __HAL_SPI_ENABLE_IT(__HANDLE__, __INTERRUPT__) SET_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__)) /** @brief Disable the specified SPI interrupts. * @param __HANDLE__ specifies the SPI handle. * This parameter can be SPIx where x: 1, 2, or 3 to select the SPI peripheral. * @param __INTERRUPT__ specifies the interrupt source to disable. * This parameter can be one of the following values: * @arg SPI_IT_TXE: Tx buffer empty interrupt enable * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable * @arg SPI_IT_ERR: Error interrupt enable * @retval None */ #define __HAL_SPI_DISABLE_IT(__HANDLE__, __INTERRUPT__) CLEAR_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__)) /** @brief Check whether the specified SPI interrupt source is enabled or not. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @param __INTERRUPT__ specifies the SPI interrupt source to check. * This parameter can be one of the following values: * @arg SPI_IT_TXE: Tx buffer empty interrupt enable * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable * @arg SPI_IT_ERR: Error interrupt enable * @retval The new state of __IT__ (TRUE or FALSE). */ #define __HAL_SPI_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2\ & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) /** @brief Check whether the specified SPI flag is set or not. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @param __FLAG__ specifies the flag to check. * This parameter can be one of the following values: * @arg SPI_FLAG_RXNE: Receive buffer not empty flag * @arg SPI_FLAG_TXE: Transmit buffer empty flag * @arg SPI_FLAG_CRCERR: CRC error flag * @arg SPI_FLAG_MODF: Mode fault flag * @arg SPI_FLAG_OVR: Overrun flag * @arg SPI_FLAG_BSY: Busy flag * @arg SPI_FLAG_FRE: Frame format error flag * @arg SPI_FLAG_FTLVL: SPI fifo transmission level * @arg SPI_FLAG_FRLVL: SPI fifo reception level * @retval The new state of __FLAG__ (TRUE or FALSE). */ #define __HAL_SPI_GET_FLAG(__HANDLE__, __FLAG__) ((((__HANDLE__)->Instance->SR) & (__FLAG__)) == (__FLAG__)) /** @brief Clear the SPI CRCERR pending flag. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @retval None */ #define __HAL_SPI_CLEAR_CRCERRFLAG(__HANDLE__) ((__HANDLE__)->Instance->SR = (uint16_t)(~SPI_FLAG_CRCERR)) /** @brief Clear the SPI MODF pending flag. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @retval None */ #define __HAL_SPI_CLEAR_MODFFLAG(__HANDLE__) \ do{ \ __IO uint32_t tmpreg_modf = 0x00U; \ tmpreg_modf = (__HANDLE__)->Instance->SR; \ CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE); \ UNUSED(tmpreg_modf); \ } while(0U) /** @brief Clear the SPI OVR pending flag. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @retval None */ #define __HAL_SPI_CLEAR_OVRFLAG(__HANDLE__) \ do{ \ __IO uint32_t tmpreg_ovr = 0x00U; \ tmpreg_ovr = (__HANDLE__)->Instance->DR; \ tmpreg_ovr = (__HANDLE__)->Instance->SR; \ UNUSED(tmpreg_ovr); \ } while(0U) /** @brief Clear the SPI FRE pending flag. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @retval None */ #define __HAL_SPI_CLEAR_FREFLAG(__HANDLE__) \ do{ \ __IO uint32_t tmpreg_fre = 0x00U; \ tmpreg_fre = (__HANDLE__)->Instance->SR; \ UNUSED(tmpreg_fre); \ } while(0U) /** @brief Enable the SPI peripheral. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @retval None */ #define __HAL_SPI_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE) /** @brief Disable the SPI peripheral. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @retval None */ #define __HAL_SPI_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE) /** * @} */ /* Private macros ------------------------------------------------------------*/ /** @defgroup SPI_Private_Macros SPI Private Macros * @{ */ /** @brief Set the SPI transmit-only mode. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @retval None */ #define SPI_1LINE_TX(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_BIDIOE) /** @brief Set the SPI receive-only mode. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @retval None */ #define SPI_1LINE_RX(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_BIDIOE) /** @brief Reset the CRC calculation of the SPI. * @param __HANDLE__ specifies the SPI Handle. * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. * @retval None */ #define SPI_RESET_CRC(__HANDLE__) \ do{ \ CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_CRCEN); \ SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_CRCEN); \ } while(0U) /** @brief Check whether the specified SPI flag is set or not. * @param __SR__ copy of SPI SR register. * @param __FLAG__ specifies the flag to check. * This parameter can be one of the following values: * @arg SPI_FLAG_RXNE: Receive buffer not empty flag * @arg SPI_FLAG_TXE: Transmit buffer empty flag * @arg SPI_FLAG_CRCERR: CRC error flag * @arg SPI_FLAG_MODF: Mode fault flag * @arg SPI_FLAG_OVR: Overrun flag * @arg SPI_FLAG_BSY: Busy flag * @arg SPI_FLAG_FRE: Frame format error flag * @arg SPI_FLAG_FTLVL: SPI fifo transmission level * @arg SPI_FLAG_FRLVL: SPI fifo reception level * @retval SET or RESET. */ #define SPI_CHECK_FLAG(__SR__, __FLAG__) ((((__SR__) & ((__FLAG__) & SPI_FLAG_MASK)) == \ ((__FLAG__) & SPI_FLAG_MASK)) ? SET : RESET) /** @brief Check whether the specified SPI Interrupt is set or not. * @param __CR2__ copy of SPI CR2 register. * @param __INTERRUPT__ specifies the SPI interrupt source to check. * This parameter can be one of the following values: * @arg SPI_IT_TXE: Tx buffer empty interrupt enable * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable * @arg SPI_IT_ERR: Error interrupt enable * @retval SET or RESET. */ #define SPI_CHECK_IT_SOURCE(__CR2__, __INTERRUPT__) ((((__CR2__) & (__INTERRUPT__)) == \ (__INTERRUPT__)) ? SET : RESET) /** @brief Checks if SPI Mode parameter is in allowed range. * @param __MODE__ specifies the SPI Mode. * This parameter can be a value of @ref SPI_Mode * @retval None */ #define IS_SPI_MODE(__MODE__) (((__MODE__) == SPI_MODE_SLAVE) || \ ((__MODE__) == SPI_MODE_MASTER)) /** @brief Checks if SPI Direction Mode parameter is in allowed range. * @param __MODE__ specifies the SPI Direction Mode. * This parameter can be a value of @ref SPI_Direction * @retval None */ #define IS_SPI_DIRECTION(__MODE__) (((__MODE__) == SPI_DIRECTION_2LINES) || \ ((__MODE__) == SPI_DIRECTION_2LINES_RXONLY) || \ ((__MODE__) == SPI_DIRECTION_1LINE)) /** @brief Checks if SPI Direction Mode parameter is 2 lines. * @param __MODE__ specifies the SPI Direction Mode. * @retval None */ #define IS_SPI_DIRECTION_2LINES(__MODE__) ((__MODE__) == SPI_DIRECTION_2LINES) /** @brief Checks if SPI Direction Mode parameter is 1 or 2 lines. * @param __MODE__ specifies the SPI Direction Mode. * @retval None */ #define IS_SPI_DIRECTION_2LINES_OR_1LINE(__MODE__) (((__MODE__) == SPI_DIRECTION_2LINES) || \ ((__MODE__) == SPI_DIRECTION_1LINE)) /** @brief Checks if SPI Data Size parameter is in allowed range. * @param __DATASIZE__ specifies the SPI Data Size. * This parameter can be a value of @ref SPI_Data_Size * @retval None */ #define IS_SPI_DATASIZE(__DATASIZE__) (((__DATASIZE__) == SPI_DATASIZE_16BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_15BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_14BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_13BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_12BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_11BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_10BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_9BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_8BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_7BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_6BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_5BIT) || \ ((__DATASIZE__) == SPI_DATASIZE_4BIT)) /** @brief Checks if SPI Serial clock steady state parameter is in allowed range. * @param __CPOL__ specifies the SPI serial clock steady state. * This parameter can be a value of @ref SPI_Clock_Polarity * @retval None */ #define IS_SPI_CPOL(__CPOL__) (((__CPOL__) == SPI_POLARITY_LOW) || \ ((__CPOL__) == SPI_POLARITY_HIGH)) /** @brief Checks if SPI Clock Phase parameter is in allowed range. * @param __CPHA__ specifies the SPI Clock Phase. * This parameter can be a value of @ref SPI_Clock_Phase * @retval None */ #define IS_SPI_CPHA(__CPHA__) (((__CPHA__) == SPI_PHASE_1EDGE) || \ ((__CPHA__) == SPI_PHASE_2EDGE)) /** @brief Checks if SPI Slave Select parameter is in allowed range. * @param __NSS__ specifies the SPI Slave Select management parameter. * This parameter can be a value of @ref SPI_Slave_Select_management * @retval None */ #define IS_SPI_NSS(__NSS__) (((__NSS__) == SPI_NSS_SOFT) || \ ((__NSS__) == SPI_NSS_HARD_INPUT) || \ ((__NSS__) == SPI_NSS_HARD_OUTPUT)) /** @brief Checks if SPI NSS Pulse parameter is in allowed range. * @param __NSSP__ specifies the SPI NSS Pulse Mode parameter. * This parameter can be a value of @ref SPI_NSSP_Mode * @retval None */ #define IS_SPI_NSSP(__NSSP__) (((__NSSP__) == SPI_NSS_PULSE_ENABLE) || \ ((__NSSP__) == SPI_NSS_PULSE_DISABLE)) /** @brief Checks if SPI Baudrate prescaler parameter is in allowed range. * @param __PRESCALER__ specifies the SPI Baudrate prescaler. * This parameter can be a value of @ref SPI_BaudRate_Prescaler * @retval None */ #define IS_SPI_BAUDRATE_PRESCALER(__PRESCALER__) (((__PRESCALER__) == SPI_BAUDRATEPRESCALER_2) || \ ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_4) || \ ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_8) || \ ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_16) || \ ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_32) || \ ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_64) || \ ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_128) || \ ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_256)) /** @brief Checks if SPI MSB LSB transmission parameter is in allowed range. * @param __BIT__ specifies the SPI MSB LSB transmission (whether data transfer starts from MSB or LSB bit). * This parameter can be a value of @ref SPI_MSB_LSB_transmission * @retval None */ #define IS_SPI_FIRST_BIT(__BIT__) (((__BIT__) == SPI_FIRSTBIT_MSB) || \ ((__BIT__) == SPI_FIRSTBIT_LSB)) /** @brief Checks if SPI TI mode parameter is in allowed range. * @param __MODE__ specifies the SPI TI mode. * This parameter can be a value of @ref SPI_TI_mode * @retval None */ #define IS_SPI_TIMODE(__MODE__) (((__MODE__) == SPI_TIMODE_DISABLE) || \ ((__MODE__) == SPI_TIMODE_ENABLE)) /** @brief Checks if SPI CRC calculation enabled state is in allowed range. * @param __CALCULATION__ specifies the SPI CRC calculation enable state. * This parameter can be a value of @ref SPI_CRC_Calculation * @retval None */ #define IS_SPI_CRC_CALCULATION(__CALCULATION__) (((__CALCULATION__) == SPI_CRCCALCULATION_DISABLE) || \ ((__CALCULATION__) == SPI_CRCCALCULATION_ENABLE)) /** @brief Checks if SPI CRC length is in allowed range. * @param __LENGTH__ specifies the SPI CRC length. * This parameter can be a value of @ref SPI_CRC_length * @retval None */ #define IS_SPI_CRC_LENGTH(__LENGTH__) (((__LENGTH__) == SPI_CRC_LENGTH_DATASIZE) || \ ((__LENGTH__) == SPI_CRC_LENGTH_8BIT) || \ ((__LENGTH__) == SPI_CRC_LENGTH_16BIT)) /** @brief Checks if SPI polynomial value to be used for the CRC calculation, is in allowed range. * @param __POLYNOMIAL__ specifies the SPI polynomial value to be used for the CRC calculation. * This parameter must be a number between Min_Data = 0 and Max_Data = 65535 * @retval None */ #define IS_SPI_CRC_POLYNOMIAL(__POLYNOMIAL__) (((__POLYNOMIAL__) >= 0x1U) && \ ((__POLYNOMIAL__) <= 0xFFFFU) && \ (((__POLYNOMIAL__)&0x1U) != 0U)) /** @brief Checks if DMA handle is valid. * @param __HANDLE__ specifies a DMA Handle. * @retval None */ #define IS_SPI_DMA_HANDLE(__HANDLE__) ((__HANDLE__) != NULL) /** * @} */ /* Include SPI HAL Extended module */ #include "stm32l4xx_hal_spi_ex.h" /* Exported functions --------------------------------------------------------*/ /** @addtogroup SPI_Exported_Functions * @{ */ /** @addtogroup SPI_Exported_Functions_Group1 * @{ */ /* Initialization/de-initialization functions ********************************/ HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi); HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi); void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi); void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi); /* Callbacks Register/UnRegister functions ***********************************/ #if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID, pSPI_CallbackTypeDef pCallback); HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID); #endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ /** * @} */ /** @addtogroup SPI_Exported_Functions_Group2 * @{ */ /* I/O operation functions ***************************************************/ HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size, uint32_t Timeout); HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout); HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout); HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size); HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size); HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, uint16_t Size); HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size); HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size); HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, uint16_t Size); HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi); HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi); HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi); /* Transfer Abort functions */ HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *hspi); HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *hspi); void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi); void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi); void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi); void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi); void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi); void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi); void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi); void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi); void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi); /** * @} */ /** @addtogroup SPI_Exported_Functions_Group3 * @{ */ /* Peripheral State and Error functions ***************************************/ HAL_SPI_StateTypeDef HAL_SPI_GetState(const SPI_HandleTypeDef *hspi); uint32_t HAL_SPI_GetError(const SPI_HandleTypeDef *hspi); /** * @} */ /** * @} */ /** * @} */ /** * @} */ #ifdef __cplusplus } #endif #endif /* STM32L4xx_HAL_SPI_H */ Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_spi_ex.h
New file @@ -0,0 +1,73 @@ /** ****************************************************************************** * @file stm32l4xx_hal_spi_ex.h * @author MCD Application Team * @brief Header file of SPI HAL Extended module. ****************************************************************************** * @attention * * Copyright (c) 2017 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef STM32L4xx_HAL_SPI_EX_H #define STM32L4xx_HAL_SPI_EX_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "stm32l4xx_hal_def.h" /** @addtogroup STM32L4xx_HAL_Driver * @{ */ /** @addtogroup SPIEx * @{ */ /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ /* Exported macros -----------------------------------------------------------*/ /* Exported functions --------------------------------------------------------*/ /** @addtogroup SPIEx_Exported_Functions * @{ */ /* Initialization and de-initialization functions ****************************/ /* IO operation functions *****************************************************/ /** @addtogroup SPIEx_Exported_Functions_Group1 * @{ */ HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(const SPI_HandleTypeDef *hspi); /** * @} */ /** * @} */ /** * @} */ /** * @} */ #ifdef __cplusplus } #endif #endif /* STM32L4xx_HAL_SPI_EX_H */ Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_i2c.h
File was deleted Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_spi.h
New file @@ -0,0 +1,1433 @@ /** ****************************************************************************** * @file stm32l4xx_ll_spi.h * @author MCD Application Team * @brief Header file of SPI LL module. ****************************************************************************** * @attention * * Copyright (c) 2017 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef STM32L4xx_LL_SPI_H #define STM32L4xx_LL_SPI_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "stm32l4xx.h" /** @addtogroup STM32L4xx_LL_Driver * @{ */ #if defined (SPI1) || defined (SPI2) || defined (SPI3) /** @defgroup SPI_LL SPI * @{ */ /* Private types -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private macros ------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/ #if defined(USE_FULL_LL_DRIVER) /** @defgroup SPI_LL_ES_INIT SPI Exported Init structure * @{ */ /** * @brief SPI Init structures definition */ typedef struct { uint32_t TransferDirection; /*!< Specifies the SPI unidirectional or bidirectional data mode. This parameter can be a value of @ref SPI_LL_EC_TRANSFER_MODE. This feature can be modified afterwards using unitary function @ref LL_SPI_SetTransferDirection().*/ uint32_t Mode; /*!< Specifies the SPI mode (Master/Slave). This parameter can be a value of @ref SPI_LL_EC_MODE. This feature can be modified afterwards using unitary function @ref LL_SPI_SetMode().*/ uint32_t DataWidth; /*!< Specifies the SPI data width. This parameter can be a value of @ref SPI_LL_EC_DATAWIDTH. This feature can be modified afterwards using unitary function @ref LL_SPI_SetDataWidth().*/ uint32_t ClockPolarity; /*!< Specifies the serial clock steady state. This parameter can be a value of @ref SPI_LL_EC_POLARITY. This feature can be modified afterwards using unitary function @ref LL_SPI_SetClockPolarity().*/ uint32_t ClockPhase; /*!< Specifies the clock active edge for the bit capture. This parameter can be a value of @ref SPI_LL_EC_PHASE. This feature can be modified afterwards using unitary function @ref LL_SPI_SetClockPhase().*/ uint32_t NSS; /*!< Specifies whether the NSS signal is managed by hardware (NSS pin) or by software using the SSI bit. This parameter can be a value of @ref SPI_LL_EC_NSS_MODE. This feature can be modified afterwards using unitary function @ref LL_SPI_SetNSSMode().*/ uint32_t BaudRate; /*!< Specifies the BaudRate prescaler value which will be used to configure the transmit and receive SCK clock. This parameter can be a value of @ref SPI_LL_EC_BAUDRATEPRESCALER. @note The communication clock is derived from the master clock. The slave clock does not need to be set. This feature can be modified afterwards using unitary function @ref LL_SPI_SetBaudRatePrescaler().*/ uint32_t BitOrder; /*!< Specifies whether data transfers start from MSB or LSB bit. This parameter can be a value of @ref SPI_LL_EC_BIT_ORDER. This feature can be modified afterwards using unitary function @ref LL_SPI_SetTransferBitOrder().*/ uint32_t CRCCalculation; /*!< Specifies if the CRC calculation is enabled or not. This parameter can be a value of @ref SPI_LL_EC_CRC_CALCULATION. This feature can be modified afterwards using unitary functions @ref LL_SPI_EnableCRC() and @ref LL_SPI_DisableCRC().*/ uint32_t CRCPoly; /*!< Specifies the polynomial used for the CRC calculation. This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF. This feature can be modified afterwards using unitary function @ref LL_SPI_SetCRCPolynomial().*/ } LL_SPI_InitTypeDef; /** * @} */ #endif /* USE_FULL_LL_DRIVER */ /* Exported constants --------------------------------------------------------*/ /** @defgroup SPI_LL_Exported_Constants SPI Exported Constants * @{ */ /** @defgroup SPI_LL_EC_GET_FLAG Get Flags Defines * @brief Flags defines which can be used with LL_SPI_ReadReg function * @{ */ #define LL_SPI_SR_RXNE SPI_SR_RXNE /*!< Rx buffer not empty flag */ #define LL_SPI_SR_TXE SPI_SR_TXE /*!< Tx buffer empty flag */ #define LL_SPI_SR_BSY SPI_SR_BSY /*!< Busy flag */ #define LL_SPI_SR_CRCERR SPI_SR_CRCERR /*!< CRC error flag */ #define LL_SPI_SR_MODF SPI_SR_MODF /*!< Mode fault flag */ #define LL_SPI_SR_OVR SPI_SR_OVR /*!< Overrun flag */ #define LL_SPI_SR_FRE SPI_SR_FRE /*!< TI mode frame format error flag */ /** * @} */ /** @defgroup SPI_LL_EC_IT IT Defines * @brief IT defines which can be used with LL_SPI_ReadReg and LL_SPI_WriteReg functions * @{ */ #define LL_SPI_CR2_RXNEIE SPI_CR2_RXNEIE /*!< Rx buffer not empty interrupt enable */ #define LL_SPI_CR2_TXEIE SPI_CR2_TXEIE /*!< Tx buffer empty interrupt enable */ #define LL_SPI_CR2_ERRIE SPI_CR2_ERRIE /*!< Error interrupt enable */ /** * @} */ /** @defgroup SPI_LL_EC_MODE Operation Mode * @{ */ #define LL_SPI_MODE_MASTER (SPI_CR1_MSTR | SPI_CR1_SSI) /*!< Master configuration */ #define LL_SPI_MODE_SLAVE 0x00000000U /*!< Slave configuration */ /** * @} */ /** @defgroup SPI_LL_EC_PROTOCOL Serial Protocol * @{ */ #define LL_SPI_PROTOCOL_MOTOROLA 0x00000000U /*!< Motorola mode. Used as default value */ #define LL_SPI_PROTOCOL_TI (SPI_CR2_FRF) /*!< TI mode */ /** * @} */ /** @defgroup SPI_LL_EC_PHASE Clock Phase * @{ */ #define LL_SPI_PHASE_1EDGE 0x00000000U /*!< First clock transition is the first data capture edge */ #define LL_SPI_PHASE_2EDGE (SPI_CR1_CPHA) /*!< Second clock transition is the first data capture edge */ /** * @} */ /** @defgroup SPI_LL_EC_POLARITY Clock Polarity * @{ */ #define LL_SPI_POLARITY_LOW 0x00000000U /*!< Clock to 0 when idle */ #define LL_SPI_POLARITY_HIGH (SPI_CR1_CPOL) /*!< Clock to 1 when idle */ /** * @} */ /** @defgroup SPI_LL_EC_BAUDRATEPRESCALER Baud Rate Prescaler * @{ */ #define LL_SPI_BAUDRATEPRESCALER_DIV2 0x00000000U /*!< BaudRate control equal to fPCLK/2 */ #define LL_SPI_BAUDRATEPRESCALER_DIV4 (SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/4 */ #define LL_SPI_BAUDRATEPRESCALER_DIV8 (SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/8 */ #define LL_SPI_BAUDRATEPRESCALER_DIV16 (SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/16 */ #define LL_SPI_BAUDRATEPRESCALER_DIV32 (SPI_CR1_BR_2) /*!< BaudRate control equal to fPCLK/32 */ #define LL_SPI_BAUDRATEPRESCALER_DIV64 (SPI_CR1_BR_2 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/64 */ #define LL_SPI_BAUDRATEPRESCALER_DIV128 (SPI_CR1_BR_2 | SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/128 */ #define LL_SPI_BAUDRATEPRESCALER_DIV256 (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/256 */ /** * @} */ /** @defgroup SPI_LL_EC_BIT_ORDER Transmission Bit Order * @{ */ #define LL_SPI_LSB_FIRST (SPI_CR1_LSBFIRST) /*!< Data is transmitted/received with the LSB first */ #define LL_SPI_MSB_FIRST 0x00000000U /*!< Data is transmitted/received with the MSB first */ /** * @} */ /** @defgroup SPI_LL_EC_TRANSFER_MODE Transfer Mode * @{ */ #define LL_SPI_FULL_DUPLEX 0x00000000U /*!< Full-Duplex mode. Rx and Tx transfer on 2 lines */ #define LL_SPI_SIMPLEX_RX (SPI_CR1_RXONLY) /*!< Simplex Rx mode. Rx transfer only on 1 line */ #define LL_SPI_HALF_DUPLEX_RX (SPI_CR1_BIDIMODE) /*!< Half-Duplex Rx mode. Rx transfer on 1 line */ #define LL_SPI_HALF_DUPLEX_TX (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE) /*!< Half-Duplex Tx mode. Tx transfer on 1 line */ /** * @} */ /** @defgroup SPI_LL_EC_NSS_MODE Slave Select Pin Mode * @{ */ #define LL_SPI_NSS_SOFT (SPI_CR1_SSM) /*!< NSS managed internally. NSS pin not used and free */ #define LL_SPI_NSS_HARD_INPUT 0x00000000U /*!< NSS pin used in Input. Only used in Master mode */ #define LL_SPI_NSS_HARD_OUTPUT (((uint32_t)SPI_CR2_SSOE << 16U)) /*!< NSS pin used in Output. Only used in Slave mode as chip select */ /** * @} */ /** @defgroup SPI_LL_EC_DATAWIDTH Datawidth * @{ */ #define LL_SPI_DATAWIDTH_4BIT (SPI_CR2_DS_0 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 4 bits */ #define LL_SPI_DATAWIDTH_5BIT (SPI_CR2_DS_2) /*!< Data length for SPI transfer: 5 bits */ #define LL_SPI_DATAWIDTH_6BIT (SPI_CR2_DS_2 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 6 bits */ #define LL_SPI_DATAWIDTH_7BIT (SPI_CR2_DS_2 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 7 bits */ #define LL_SPI_DATAWIDTH_8BIT (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 8 bits */ #define LL_SPI_DATAWIDTH_9BIT (SPI_CR2_DS_3) /*!< Data length for SPI transfer: 9 bits */ #define LL_SPI_DATAWIDTH_10BIT (SPI_CR2_DS_3 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 10 bits */ #define LL_SPI_DATAWIDTH_11BIT (SPI_CR2_DS_3 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 11 bits */ #define LL_SPI_DATAWIDTH_12BIT (SPI_CR2_DS_3 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 12 bits */ #define LL_SPI_DATAWIDTH_13BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2) /*!< Data length for SPI transfer: 13 bits */ #define LL_SPI_DATAWIDTH_14BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 14 bits */ #define LL_SPI_DATAWIDTH_15BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 15 bits */ #define LL_SPI_DATAWIDTH_16BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 16 bits */ /** * @} */ #if defined(USE_FULL_LL_DRIVER) /** @defgroup SPI_LL_EC_CRC_CALCULATION CRC Calculation * @{ */ #define LL_SPI_CRCCALCULATION_DISABLE 0x00000000U /*!< CRC calculation disabled */ #define LL_SPI_CRCCALCULATION_ENABLE (SPI_CR1_CRCEN) /*!< CRC calculation enabled */ /** * @} */ #endif /* USE_FULL_LL_DRIVER */ /** @defgroup SPI_LL_EC_CRC_LENGTH CRC Length * @{ */ #define LL_SPI_CRC_8BIT 0x00000000U /*!< 8-bit CRC length */ #define LL_SPI_CRC_16BIT (SPI_CR1_CRCL) /*!< 16-bit CRC length */ /** * @} */ /** @defgroup SPI_LL_EC_RX_FIFO_TH RX FIFO Threshold * @{ */ #define LL_SPI_RX_FIFO_TH_HALF 0x00000000U /*!< RXNE event is generated if FIFO level is greater than or equal to 1/2 (16-bit) */ #define LL_SPI_RX_FIFO_TH_QUARTER (SPI_CR2_FRXTH) /*!< RXNE event is generated if FIFO level is greater than or equal to 1/4 (8-bit) */ /** * @} */ /** @defgroup SPI_LL_EC_RX_FIFO RX FIFO Level * @{ */ #define LL_SPI_RX_FIFO_EMPTY 0x00000000U /*!< FIFO reception empty */ #define LL_SPI_RX_FIFO_QUARTER_FULL (SPI_SR_FRLVL_0) /*!< FIFO reception 1/4 */ #define LL_SPI_RX_FIFO_HALF_FULL (SPI_SR_FRLVL_1) /*!< FIFO reception 1/2 */ #define LL_SPI_RX_FIFO_FULL (SPI_SR_FRLVL_1 | SPI_SR_FRLVL_0) /*!< FIFO reception full */ /** * @} */ /** @defgroup SPI_LL_EC_TX_FIFO TX FIFO Level * @{ */ #define LL_SPI_TX_FIFO_EMPTY 0x00000000U /*!< FIFO transmission empty */ #define LL_SPI_TX_FIFO_QUARTER_FULL (SPI_SR_FTLVL_0) /*!< FIFO transmission 1/4 */ #define LL_SPI_TX_FIFO_HALF_FULL (SPI_SR_FTLVL_1) /*!< FIFO transmission 1/2 */ #define LL_SPI_TX_FIFO_FULL (SPI_SR_FTLVL_1 | SPI_SR_FTLVL_0) /*!< FIFO transmission full */ /** * @} */ /** @defgroup SPI_LL_EC_DMA_PARITY DMA Parity * @{ */ #define LL_SPI_DMA_PARITY_EVEN 0x00000000U /*!< Select DMA parity Even */ #define LL_SPI_DMA_PARITY_ODD 0x00000001U /*!< Select DMA parity Odd */ /** * @} */ /** * @} */ /* Exported macro ------------------------------------------------------------*/ /** @defgroup SPI_LL_Exported_Macros SPI Exported Macros * @{ */ /** @defgroup SPI_LL_EM_WRITE_READ Common Write and read registers Macros * @{ */ /** * @brief Write a value in SPI register * @param __INSTANCE__ SPI Instance * @param __REG__ Register to be written * @param __VALUE__ Value to be written in the register * @retval None */ #define LL_SPI_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) /** * @brief Read a value in SPI register * @param __INSTANCE__ SPI Instance * @param __REG__ Register to be read * @retval Register value */ #define LL_SPI_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) /** * @} */ /** * @} */ /* Exported functions --------------------------------------------------------*/ /** @defgroup SPI_LL_Exported_Functions SPI Exported Functions * @{ */ /** @defgroup SPI_LL_EF_Configuration Configuration * @{ */ /** * @brief Enable SPI peripheral * @rmtoll CR1 SPE LL_SPI_Enable * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_Enable(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR1, SPI_CR1_SPE); } /** * @brief Disable SPI peripheral * @note When disabling the SPI, follow the procedure described in the Reference Manual. * @rmtoll CR1 SPE LL_SPI_Disable * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_Disable(SPI_TypeDef *SPIx) { CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); } /** * @brief Check if SPI peripheral is enabled * @rmtoll CR1 SPE LL_SPI_IsEnabled * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsEnabled(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->CR1, SPI_CR1_SPE) == (SPI_CR1_SPE)) ? 1UL : 0UL); } /** * @brief Set SPI operation mode to Master or Slave * @note This bit should not be changed when communication is ongoing. * @rmtoll CR1 MSTR LL_SPI_SetMode\n * CR1 SSI LL_SPI_SetMode * @param SPIx SPI Instance * @param Mode This parameter can be one of the following values: * @arg @ref LL_SPI_MODE_MASTER * @arg @ref LL_SPI_MODE_SLAVE * @retval None */ __STATIC_INLINE void LL_SPI_SetMode(SPI_TypeDef *SPIx, uint32_t Mode) { MODIFY_REG(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI, Mode); } /** * @brief Get SPI operation mode (Master or Slave) * @rmtoll CR1 MSTR LL_SPI_GetMode\n * CR1 SSI LL_SPI_GetMode * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_MODE_MASTER * @arg @ref LL_SPI_MODE_SLAVE */ __STATIC_INLINE uint32_t LL_SPI_GetMode(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI)); } /** * @brief Set serial protocol used * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. * @rmtoll CR2 FRF LL_SPI_SetStandard * @param SPIx SPI Instance * @param Standard This parameter can be one of the following values: * @arg @ref LL_SPI_PROTOCOL_MOTOROLA * @arg @ref LL_SPI_PROTOCOL_TI * @retval None */ __STATIC_INLINE void LL_SPI_SetStandard(SPI_TypeDef *SPIx, uint32_t Standard) { MODIFY_REG(SPIx->CR2, SPI_CR2_FRF, Standard); } /** * @brief Get serial protocol used * @rmtoll CR2 FRF LL_SPI_GetStandard * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_PROTOCOL_MOTOROLA * @arg @ref LL_SPI_PROTOCOL_TI */ __STATIC_INLINE uint32_t LL_SPI_GetStandard(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRF)); } /** * @brief Set clock phase * @note This bit should not be changed when communication is ongoing. * This bit is not used in SPI TI mode. * @rmtoll CR1 CPHA LL_SPI_SetClockPhase * @param SPIx SPI Instance * @param ClockPhase This parameter can be one of the following values: * @arg @ref LL_SPI_PHASE_1EDGE * @arg @ref LL_SPI_PHASE_2EDGE * @retval None */ __STATIC_INLINE void LL_SPI_SetClockPhase(SPI_TypeDef *SPIx, uint32_t ClockPhase) { MODIFY_REG(SPIx->CR1, SPI_CR1_CPHA, ClockPhase); } /** * @brief Get clock phase * @rmtoll CR1 CPHA LL_SPI_GetClockPhase * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_PHASE_1EDGE * @arg @ref LL_SPI_PHASE_2EDGE */ __STATIC_INLINE uint32_t LL_SPI_GetClockPhase(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPHA)); } /** * @brief Set clock polarity * @note This bit should not be changed when communication is ongoing. * This bit is not used in SPI TI mode. * @rmtoll CR1 CPOL LL_SPI_SetClockPolarity * @param SPIx SPI Instance * @param ClockPolarity This parameter can be one of the following values: * @arg @ref LL_SPI_POLARITY_LOW * @arg @ref LL_SPI_POLARITY_HIGH * @retval None */ __STATIC_INLINE void LL_SPI_SetClockPolarity(SPI_TypeDef *SPIx, uint32_t ClockPolarity) { MODIFY_REG(SPIx->CR1, SPI_CR1_CPOL, ClockPolarity); } /** * @brief Get clock polarity * @rmtoll CR1 CPOL LL_SPI_GetClockPolarity * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_POLARITY_LOW * @arg @ref LL_SPI_POLARITY_HIGH */ __STATIC_INLINE uint32_t LL_SPI_GetClockPolarity(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPOL)); } /** * @brief Set baud rate prescaler * @note These bits should not be changed when communication is ongoing. SPI BaudRate = fPCLK/Prescaler. * @rmtoll CR1 BR LL_SPI_SetBaudRatePrescaler * @param SPIx SPI Instance * @param BaudRate This parameter can be one of the following values: * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 * @retval None */ __STATIC_INLINE void LL_SPI_SetBaudRatePrescaler(SPI_TypeDef *SPIx, uint32_t BaudRate) { MODIFY_REG(SPIx->CR1, SPI_CR1_BR, BaudRate); } /** * @brief Get baud rate prescaler * @rmtoll CR1 BR LL_SPI_GetBaudRatePrescaler * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 */ __STATIC_INLINE uint32_t LL_SPI_GetBaudRatePrescaler(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_BR)); } /** * @brief Set transfer bit order * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. * @rmtoll CR1 LSBFIRST LL_SPI_SetTransferBitOrder * @param SPIx SPI Instance * @param BitOrder This parameter can be one of the following values: * @arg @ref LL_SPI_LSB_FIRST * @arg @ref LL_SPI_MSB_FIRST * @retval None */ __STATIC_INLINE void LL_SPI_SetTransferBitOrder(SPI_TypeDef *SPIx, uint32_t BitOrder) { MODIFY_REG(SPIx->CR1, SPI_CR1_LSBFIRST, BitOrder); } /** * @brief Get transfer bit order * @rmtoll CR1 LSBFIRST LL_SPI_GetTransferBitOrder * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_LSB_FIRST * @arg @ref LL_SPI_MSB_FIRST */ __STATIC_INLINE uint32_t LL_SPI_GetTransferBitOrder(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_LSBFIRST)); } /** * @brief Set transfer direction mode * @note For Half-Duplex mode, Rx Direction is set by default. * In master mode, the MOSI pin is used and in slave mode, the MISO pin is used for Half-Duplex. * @rmtoll CR1 RXONLY LL_SPI_SetTransferDirection\n * CR1 BIDIMODE LL_SPI_SetTransferDirection\n * CR1 BIDIOE LL_SPI_SetTransferDirection * @param SPIx SPI Instance * @param TransferDirection This parameter can be one of the following values: * @arg @ref LL_SPI_FULL_DUPLEX * @arg @ref LL_SPI_SIMPLEX_RX * @arg @ref LL_SPI_HALF_DUPLEX_RX * @arg @ref LL_SPI_HALF_DUPLEX_TX * @retval None */ __STATIC_INLINE void LL_SPI_SetTransferDirection(SPI_TypeDef *SPIx, uint32_t TransferDirection) { MODIFY_REG(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE, TransferDirection); } /** * @brief Get transfer direction mode * @rmtoll CR1 RXONLY LL_SPI_GetTransferDirection\n * CR1 BIDIMODE LL_SPI_GetTransferDirection\n * CR1 BIDIOE LL_SPI_GetTransferDirection * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_FULL_DUPLEX * @arg @ref LL_SPI_SIMPLEX_RX * @arg @ref LL_SPI_HALF_DUPLEX_RX * @arg @ref LL_SPI_HALF_DUPLEX_TX */ __STATIC_INLINE uint32_t LL_SPI_GetTransferDirection(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE)); } /** * @brief Set frame data width * @rmtoll CR2 DS LL_SPI_SetDataWidth * @param SPIx SPI Instance * @param DataWidth This parameter can be one of the following values: * @arg @ref LL_SPI_DATAWIDTH_4BIT * @arg @ref LL_SPI_DATAWIDTH_5BIT * @arg @ref LL_SPI_DATAWIDTH_6BIT * @arg @ref LL_SPI_DATAWIDTH_7BIT * @arg @ref LL_SPI_DATAWIDTH_8BIT * @arg @ref LL_SPI_DATAWIDTH_9BIT * @arg @ref LL_SPI_DATAWIDTH_10BIT * @arg @ref LL_SPI_DATAWIDTH_11BIT * @arg @ref LL_SPI_DATAWIDTH_12BIT * @arg @ref LL_SPI_DATAWIDTH_13BIT * @arg @ref LL_SPI_DATAWIDTH_14BIT * @arg @ref LL_SPI_DATAWIDTH_15BIT * @arg @ref LL_SPI_DATAWIDTH_16BIT * @retval None */ __STATIC_INLINE void LL_SPI_SetDataWidth(SPI_TypeDef *SPIx, uint32_t DataWidth) { MODIFY_REG(SPIx->CR2, SPI_CR2_DS, DataWidth); } /** * @brief Get frame data width * @rmtoll CR2 DS LL_SPI_GetDataWidth * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_DATAWIDTH_4BIT * @arg @ref LL_SPI_DATAWIDTH_5BIT * @arg @ref LL_SPI_DATAWIDTH_6BIT * @arg @ref LL_SPI_DATAWIDTH_7BIT * @arg @ref LL_SPI_DATAWIDTH_8BIT * @arg @ref LL_SPI_DATAWIDTH_9BIT * @arg @ref LL_SPI_DATAWIDTH_10BIT * @arg @ref LL_SPI_DATAWIDTH_11BIT * @arg @ref LL_SPI_DATAWIDTH_12BIT * @arg @ref LL_SPI_DATAWIDTH_13BIT * @arg @ref LL_SPI_DATAWIDTH_14BIT * @arg @ref LL_SPI_DATAWIDTH_15BIT * @arg @ref LL_SPI_DATAWIDTH_16BIT */ __STATIC_INLINE uint32_t LL_SPI_GetDataWidth(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_DS)); } /** * @brief Set threshold of RXFIFO that triggers an RXNE event * @rmtoll CR2 FRXTH LL_SPI_SetRxFIFOThreshold * @param SPIx SPI Instance * @param Threshold This parameter can be one of the following values: * @arg @ref LL_SPI_RX_FIFO_TH_HALF * @arg @ref LL_SPI_RX_FIFO_TH_QUARTER * @retval None */ __STATIC_INLINE void LL_SPI_SetRxFIFOThreshold(SPI_TypeDef *SPIx, uint32_t Threshold) { MODIFY_REG(SPIx->CR2, SPI_CR2_FRXTH, Threshold); } /** * @brief Get threshold of RXFIFO that triggers an RXNE event * @rmtoll CR2 FRXTH LL_SPI_GetRxFIFOThreshold * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_RX_FIFO_TH_HALF * @arg @ref LL_SPI_RX_FIFO_TH_QUARTER */ __STATIC_INLINE uint32_t LL_SPI_GetRxFIFOThreshold(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRXTH)); } /** * @} */ /** @defgroup SPI_LL_EF_CRC_Management CRC Management * @{ */ /** * @brief Enable CRC * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. * @rmtoll CR1 CRCEN LL_SPI_EnableCRC * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_EnableCRC(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR1, SPI_CR1_CRCEN); } /** * @brief Disable CRC * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. * @rmtoll CR1 CRCEN LL_SPI_DisableCRC * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_DisableCRC(SPI_TypeDef *SPIx) { CLEAR_BIT(SPIx->CR1, SPI_CR1_CRCEN); } /** * @brief Check if CRC is enabled * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. * @rmtoll CR1 CRCEN LL_SPI_IsEnabledCRC * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsEnabledCRC(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->CR1, SPI_CR1_CRCEN) == (SPI_CR1_CRCEN)) ? 1UL : 0UL); } /** * @brief Set CRC Length * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. * @rmtoll CR1 CRCL LL_SPI_SetCRCWidth * @param SPIx SPI Instance * @param CRCLength This parameter can be one of the following values: * @arg @ref LL_SPI_CRC_8BIT * @arg @ref LL_SPI_CRC_16BIT * @retval None */ __STATIC_INLINE void LL_SPI_SetCRCWidth(SPI_TypeDef *SPIx, uint32_t CRCLength) { MODIFY_REG(SPIx->CR1, SPI_CR1_CRCL, CRCLength); } /** * @brief Get CRC Length * @rmtoll CR1 CRCL LL_SPI_GetCRCWidth * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_CRC_8BIT * @arg @ref LL_SPI_CRC_16BIT */ __STATIC_INLINE uint32_t LL_SPI_GetCRCWidth(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CRCL)); } /** * @brief Set CRCNext to transfer CRC on the line * @note This bit has to be written as soon as the last data is written in the SPIx_DR register. * @rmtoll CR1 CRCNEXT LL_SPI_SetCRCNext * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_SetCRCNext(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR1, SPI_CR1_CRCNEXT); } /** * @brief Set polynomial for CRC calculation * @rmtoll CRCPR CRCPOLY LL_SPI_SetCRCPolynomial * @param SPIx SPI Instance * @param CRCPoly This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF * @retval None */ __STATIC_INLINE void LL_SPI_SetCRCPolynomial(SPI_TypeDef *SPIx, uint32_t CRCPoly) { WRITE_REG(SPIx->CRCPR, (uint16_t)CRCPoly); } /** * @brief Get polynomial for CRC calculation * @rmtoll CRCPR CRCPOLY LL_SPI_GetCRCPolynomial * @param SPIx SPI Instance * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF */ __STATIC_INLINE uint32_t LL_SPI_GetCRCPolynomial(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_REG(SPIx->CRCPR)); } /** * @brief Get Rx CRC * @rmtoll RXCRCR RXCRC LL_SPI_GetRxCRC * @param SPIx SPI Instance * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF */ __STATIC_INLINE uint32_t LL_SPI_GetRxCRC(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_REG(SPIx->RXCRCR)); } /** * @brief Get Tx CRC * @rmtoll TXCRCR TXCRC LL_SPI_GetTxCRC * @param SPIx SPI Instance * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF */ __STATIC_INLINE uint32_t LL_SPI_GetTxCRC(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_REG(SPIx->TXCRCR)); } /** * @} */ /** @defgroup SPI_LL_EF_NSS_Management Slave Select Pin Management * @{ */ /** * @brief Set NSS mode * @note LL_SPI_NSS_SOFT Mode is not used in SPI TI mode. * @rmtoll CR1 SSM LL_SPI_SetNSSMode\n * @rmtoll CR2 SSOE LL_SPI_SetNSSMode * @param SPIx SPI Instance * @param NSS This parameter can be one of the following values: * @arg @ref LL_SPI_NSS_SOFT * @arg @ref LL_SPI_NSS_HARD_INPUT * @arg @ref LL_SPI_NSS_HARD_OUTPUT * @retval None */ __STATIC_INLINE void LL_SPI_SetNSSMode(SPI_TypeDef *SPIx, uint32_t NSS) { MODIFY_REG(SPIx->CR1, SPI_CR1_SSM, NSS); MODIFY_REG(SPIx->CR2, SPI_CR2_SSOE, ((uint32_t)(NSS >> 16U))); } /** * @brief Get NSS mode * @rmtoll CR1 SSM LL_SPI_GetNSSMode\n * @rmtoll CR2 SSOE LL_SPI_GetNSSMode * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_NSS_SOFT * @arg @ref LL_SPI_NSS_HARD_INPUT * @arg @ref LL_SPI_NSS_HARD_OUTPUT */ __STATIC_INLINE uint32_t LL_SPI_GetNSSMode(const SPI_TypeDef *SPIx) { uint32_t Ssm = (READ_BIT(SPIx->CR1, SPI_CR1_SSM)); uint32_t Ssoe = (READ_BIT(SPIx->CR2, SPI_CR2_SSOE) << 16U); return (Ssm | Ssoe); } /** * @brief Enable NSS pulse management * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. * @rmtoll CR2 NSSP LL_SPI_EnableNSSPulseMgt * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_EnableNSSPulseMgt(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_NSSP); } /** * @brief Disable NSS pulse management * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. * @rmtoll CR2 NSSP LL_SPI_DisableNSSPulseMgt * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_DisableNSSPulseMgt(SPI_TypeDef *SPIx) { CLEAR_BIT(SPIx->CR2, SPI_CR2_NSSP); } /** * @brief Check if NSS pulse is enabled * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. * @rmtoll CR2 NSSP LL_SPI_IsEnabledNSSPulse * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsEnabledNSSPulse(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->CR2, SPI_CR2_NSSP) == (SPI_CR2_NSSP)) ? 1UL : 0UL); } /** * @} */ /** @defgroup SPI_LL_EF_FLAG_Management FLAG Management * @{ */ /** * @brief Check if Rx buffer is not empty * @rmtoll SR RXNE LL_SPI_IsActiveFlag_RXNE * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_RXNE(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->SR, SPI_SR_RXNE) == (SPI_SR_RXNE)) ? 1UL : 0UL); } /** * @brief Check if Tx buffer is empty * @rmtoll SR TXE LL_SPI_IsActiveFlag_TXE * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_TXE(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->SR, SPI_SR_TXE) == (SPI_SR_TXE)) ? 1UL : 0UL); } /** * @brief Get CRC error flag * @rmtoll SR CRCERR LL_SPI_IsActiveFlag_CRCERR * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_CRCERR(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->SR, SPI_SR_CRCERR) == (SPI_SR_CRCERR)) ? 1UL : 0UL); } /** * @brief Get mode fault error flag * @rmtoll SR MODF LL_SPI_IsActiveFlag_MODF * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_MODF(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->SR, SPI_SR_MODF) == (SPI_SR_MODF)) ? 1UL : 0UL); } /** * @brief Get overrun error flag * @rmtoll SR OVR LL_SPI_IsActiveFlag_OVR * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_OVR(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->SR, SPI_SR_OVR) == (SPI_SR_OVR)) ? 1UL : 0UL); } /** * @brief Get busy flag * @note The BSY flag is cleared under any one of the following conditions: * -When the SPI is correctly disabled * -When a fault is detected in Master mode (MODF bit set to 1) * -In Master mode, when it finishes a data transmission and no new data is ready to be * sent * -In Slave mode, when the BSY flag is set to '0' for at least one SPI clock cycle between * each data transfer. * @rmtoll SR BSY LL_SPI_IsActiveFlag_BSY * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_BSY(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->SR, SPI_SR_BSY) == (SPI_SR_BSY)) ? 1UL : 0UL); } /** * @brief Get frame format error flag * @rmtoll SR FRE LL_SPI_IsActiveFlag_FRE * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_FRE(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->SR, SPI_SR_FRE) == (SPI_SR_FRE)) ? 1UL : 0UL); } /** * @brief Get FIFO reception Level * @rmtoll SR FRLVL LL_SPI_GetRxFIFOLevel * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_RX_FIFO_EMPTY * @arg @ref LL_SPI_RX_FIFO_QUARTER_FULL * @arg @ref LL_SPI_RX_FIFO_HALF_FULL * @arg @ref LL_SPI_RX_FIFO_FULL */ __STATIC_INLINE uint32_t LL_SPI_GetRxFIFOLevel(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FRLVL)); } /** * @brief Get FIFO Transmission Level * @rmtoll SR FTLVL LL_SPI_GetTxFIFOLevel * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_TX_FIFO_EMPTY * @arg @ref LL_SPI_TX_FIFO_QUARTER_FULL * @arg @ref LL_SPI_TX_FIFO_HALF_FULL * @arg @ref LL_SPI_TX_FIFO_FULL */ __STATIC_INLINE uint32_t LL_SPI_GetTxFIFOLevel(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FTLVL)); } /** * @brief Clear CRC error flag * @rmtoll SR CRCERR LL_SPI_ClearFlag_CRCERR * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_ClearFlag_CRCERR(SPI_TypeDef *SPIx) { CLEAR_BIT(SPIx->SR, SPI_SR_CRCERR); } /** * @brief Clear mode fault error flag * @note Clearing this flag is done by a read access to the SPIx_SR * register followed by a write access to the SPIx_CR1 register * @rmtoll SR MODF LL_SPI_ClearFlag_MODF * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_ClearFlag_MODF(SPI_TypeDef *SPIx) { __IO uint32_t tmpreg_sr; tmpreg_sr = SPIx->SR; (void) tmpreg_sr; CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); } /** * @brief Clear overrun error flag * @note Clearing this flag is done by a read access to the SPIx_DR * register followed by a read access to the SPIx_SR register * @rmtoll SR OVR LL_SPI_ClearFlag_OVR * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_ClearFlag_OVR(SPI_TypeDef *SPIx) { __IO uint32_t tmpreg; tmpreg = SPIx->DR; (void) tmpreg; tmpreg = SPIx->SR; (void) tmpreg; } /** * @brief Clear frame format error flag * @note Clearing this flag is done by reading SPIx_SR register * @rmtoll SR FRE LL_SPI_ClearFlag_FRE * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_ClearFlag_FRE(SPI_TypeDef *SPIx) { __IO uint32_t tmpreg; tmpreg = SPIx->SR; (void) tmpreg; } /** * @} */ /** @defgroup SPI_LL_EF_IT_Management Interrupt Management * @{ */ /** * @brief Enable error interrupt * @note This bit controls the generation of an interrupt when an error condition * occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). * @rmtoll CR2 ERRIE LL_SPI_EnableIT_ERR * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_EnableIT_ERR(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_ERRIE); } /** * @brief Enable Rx buffer not empty interrupt * @rmtoll CR2 RXNEIE LL_SPI_EnableIT_RXNE * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_EnableIT_RXNE(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_RXNEIE); } /** * @brief Enable Tx buffer empty interrupt * @rmtoll CR2 TXEIE LL_SPI_EnableIT_TXE * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_EnableIT_TXE(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_TXEIE); } /** * @brief Disable error interrupt * @note This bit controls the generation of an interrupt when an error condition * occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). * @rmtoll CR2 ERRIE LL_SPI_DisableIT_ERR * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_DisableIT_ERR(SPI_TypeDef *SPIx) { CLEAR_BIT(SPIx->CR2, SPI_CR2_ERRIE); } /** * @brief Disable Rx buffer not empty interrupt * @rmtoll CR2 RXNEIE LL_SPI_DisableIT_RXNE * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_DisableIT_RXNE(SPI_TypeDef *SPIx) { CLEAR_BIT(SPIx->CR2, SPI_CR2_RXNEIE); } /** * @brief Disable Tx buffer empty interrupt * @rmtoll CR2 TXEIE LL_SPI_DisableIT_TXE * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_DisableIT_TXE(SPI_TypeDef *SPIx) { CLEAR_BIT(SPIx->CR2, SPI_CR2_TXEIE); } /** * @brief Check if error interrupt is enabled * @rmtoll CR2 ERRIE LL_SPI_IsEnabledIT_ERR * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_ERR(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->CR2, SPI_CR2_ERRIE) == (SPI_CR2_ERRIE)) ? 1UL : 0UL); } /** * @brief Check if Rx buffer not empty interrupt is enabled * @rmtoll CR2 RXNEIE LL_SPI_IsEnabledIT_RXNE * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_RXNE(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->CR2, SPI_CR2_RXNEIE) == (SPI_CR2_RXNEIE)) ? 1UL : 0UL); } /** * @brief Check if Tx buffer empty interrupt * @rmtoll CR2 TXEIE LL_SPI_IsEnabledIT_TXE * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_TXE(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->CR2, SPI_CR2_TXEIE) == (SPI_CR2_TXEIE)) ? 1UL : 0UL); } /** * @} */ /** @defgroup SPI_LL_EF_DMA_Management DMA Management * @{ */ /** * @brief Enable DMA Rx * @rmtoll CR2 RXDMAEN LL_SPI_EnableDMAReq_RX * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); } /** * @brief Disable DMA Rx * @rmtoll CR2 RXDMAEN LL_SPI_DisableDMAReq_RX * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_DisableDMAReq_RX(SPI_TypeDef *SPIx) { CLEAR_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); } /** * @brief Check if DMA Rx is enabled * @rmtoll CR2 RXDMAEN LL_SPI_IsEnabledDMAReq_RX * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_RX(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->CR2, SPI_CR2_RXDMAEN) == (SPI_CR2_RXDMAEN)) ? 1UL : 0UL); } /** * @brief Enable DMA Tx * @rmtoll CR2 TXDMAEN LL_SPI_EnableDMAReq_TX * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) { SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); } /** * @brief Disable DMA Tx * @rmtoll CR2 TXDMAEN LL_SPI_DisableDMAReq_TX * @param SPIx SPI Instance * @retval None */ __STATIC_INLINE void LL_SPI_DisableDMAReq_TX(SPI_TypeDef *SPIx) { CLEAR_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); } /** * @brief Check if DMA Tx is enabled * @rmtoll CR2 TXDMAEN LL_SPI_IsEnabledDMAReq_TX * @param SPIx SPI Instance * @retval State of bit (1 or 0). */ __STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_TX(const SPI_TypeDef *SPIx) { return ((READ_BIT(SPIx->CR2, SPI_CR2_TXDMAEN) == (SPI_CR2_TXDMAEN)) ? 1UL : 0UL); } /** * @brief Set parity of Last DMA reception * @rmtoll CR2 LDMARX LL_SPI_SetDMAParity_RX * @param SPIx SPI Instance * @param Parity This parameter can be one of the following values: * @arg @ref LL_SPI_DMA_PARITY_ODD * @arg @ref LL_SPI_DMA_PARITY_EVEN * @retval None */ __STATIC_INLINE void LL_SPI_SetDMAParity_RX(SPI_TypeDef *SPIx, uint32_t Parity) { MODIFY_REG(SPIx->CR2, SPI_CR2_LDMARX, (Parity << SPI_CR2_LDMARX_Pos)); } /** * @brief Get parity configuration for Last DMA reception * @rmtoll CR2 LDMARX LL_SPI_GetDMAParity_RX * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_DMA_PARITY_ODD * @arg @ref LL_SPI_DMA_PARITY_EVEN */ __STATIC_INLINE uint32_t LL_SPI_GetDMAParity_RX(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMARX) >> SPI_CR2_LDMARX_Pos); } /** * @brief Set parity of Last DMA transmission * @rmtoll CR2 LDMATX LL_SPI_SetDMAParity_TX * @param SPIx SPI Instance * @param Parity This parameter can be one of the following values: * @arg @ref LL_SPI_DMA_PARITY_ODD * @arg @ref LL_SPI_DMA_PARITY_EVEN * @retval None */ __STATIC_INLINE void LL_SPI_SetDMAParity_TX(SPI_TypeDef *SPIx, uint32_t Parity) { MODIFY_REG(SPIx->CR2, SPI_CR2_LDMATX, (Parity << SPI_CR2_LDMATX_Pos)); } /** * @brief Get parity configuration for Last DMA transmission * @rmtoll CR2 LDMATX LL_SPI_GetDMAParity_TX * @param SPIx SPI Instance * @retval Returned value can be one of the following values: * @arg @ref LL_SPI_DMA_PARITY_ODD * @arg @ref LL_SPI_DMA_PARITY_EVEN */ __STATIC_INLINE uint32_t LL_SPI_GetDMAParity_TX(const SPI_TypeDef *SPIx) { return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMATX) >> SPI_CR2_LDMATX_Pos); } /** * @brief Get the data register address used for DMA transfer * @rmtoll DR DR LL_SPI_DMA_GetRegAddr * @param SPIx SPI Instance * @retval Address of data register */ __STATIC_INLINE uint32_t LL_SPI_DMA_GetRegAddr(const SPI_TypeDef *SPIx) { return (uint32_t) &(SPIx->DR); } /** * @} */ /** @defgroup SPI_LL_EF_DATA_Management DATA Management * @{ */ /** * @brief Read 8-Bits in the data register * @rmtoll DR DR LL_SPI_ReceiveData8 * @param SPIx SPI Instance * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFF */ __STATIC_INLINE uint8_t LL_SPI_ReceiveData8(SPI_TypeDef *SPIx) { return (*((__IO uint8_t *)&SPIx->DR)); } /** * @brief Read 16-Bits in the data register * @rmtoll DR DR LL_SPI_ReceiveData16 * @param SPIx SPI Instance * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFFFF */ __STATIC_INLINE uint16_t LL_SPI_ReceiveData16(SPI_TypeDef *SPIx) { return (uint16_t)(READ_REG(SPIx->DR)); } /** * @brief Write 8-Bits in the data register * @rmtoll DR DR LL_SPI_TransmitData8 * @param SPIx SPI Instance * @param TxData Value between Min_Data=0x00 and Max_Data=0xFF * @retval None */ __STATIC_INLINE void LL_SPI_TransmitData8(SPI_TypeDef *SPIx, uint8_t TxData) { #if defined (__GNUC__) __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR); *spidr = TxData; #else *((__IO uint8_t *)&SPIx->DR) = TxData; #endif /* __GNUC__ */ } /** * @brief Write 16-Bits in the data register * @rmtoll DR DR LL_SPI_TransmitData16 * @param SPIx SPI Instance * @param TxData Value between Min_Data=0x00 and Max_Data=0xFFFF * @retval None */ __STATIC_INLINE void LL_SPI_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData) { #if defined (__GNUC__) __IO uint16_t *spidr = ((__IO uint16_t *)&SPIx->DR); *spidr = TxData; #else SPIx->DR = TxData; #endif /* __GNUC__ */ } /** * @} */ #if defined(USE_FULL_LL_DRIVER) /** @defgroup SPI_LL_EF_Init Initialization and de-initialization functions * @{ */ ErrorStatus LL_SPI_DeInit(const SPI_TypeDef *SPIx); ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct); void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct); /** * @} */ #endif /* USE_FULL_LL_DRIVER */ /** * @} */ /** * @} */ #endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */ /** * @} */ #ifdef __cplusplus } #endif #endif /* STM32L4xx_LL_SPI_H */ Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi.c
New file Diff too large Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi_ex.c
New file @@ -0,0 +1,112 @@ /** ****************************************************************************** * @file stm32l4xx_hal_spi_ex.c * @author MCD Application Team * @brief Extended SPI HAL module driver. * This file provides firmware functions to manage the following * SPI peripheral extended functionalities : * + IO operation functions * ****************************************************************************** * @attention * * Copyright (c) 2017 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stm32l4xx_hal.h" /** @addtogroup STM32L4xx_HAL_Driver * @{ */ /** @defgroup SPIEx SPIEx * @brief SPI Extended HAL module driver * @{ */ #ifdef HAL_SPI_MODULE_ENABLED /* Private typedef -----------------------------------------------------------*/ /* Private defines -----------------------------------------------------------*/ /** @defgroup SPIEx_Private_Constants SPIEx Private Constants * @{ */ #define SPI_FIFO_SIZE 4UL /** * @} */ /* Private macros ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Exported functions --------------------------------------------------------*/ /** @defgroup SPIEx_Exported_Functions SPIEx Exported Functions * @{ */ /** @defgroup SPIEx_Exported_Functions_Group1 IO operation functions * @brief Data transfers functions * @verbatim ============================================================================== ##### IO operation functions ##### =============================================================================== [..] This subsection provides a set of extended functions to manage the SPI data transfers. (#) Rx data flush function: (++) HAL_SPIEx_FlushRxFifo() @endverbatim * @{ */ /** * @brief Flush the RX fifo. * @param hspi pointer to a SPI_HandleTypeDef structure that contains * the configuration information for the specified SPI module. * @retval HAL status */ HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(const SPI_HandleTypeDef *hspi) { __IO uint32_t tmpreg; uint8_t count = 0U; while ((hspi->Instance->SR & SPI_FLAG_FRLVL) != SPI_FRLVL_EMPTY) { count++; tmpreg = hspi->Instance->DR; UNUSED(tmpreg); /* To avoid GCC warning */ if (count == SPI_FIFO_SIZE) { return HAL_TIMEOUT; } } return HAL_OK; } /** * @} */ /** * @} */ #endif /* HAL_SPI_MODULE_ENABLED */ /** * @} */ /** * @} */ ISKBoard.ioc
@@ -24,30 +24,34 @@ Mcu.IP0=ADC1 Mcu.IP1=NVIC Mcu.IP2=RCC Mcu.IP3=SYS Mcu.IP4=TIM1 Mcu.IP5=TIM6 Mcu.IP6=USART1 Mcu.IPNb=7 Mcu.IP3=SPI1 Mcu.IP4=SYS Mcu.IP5=TIM1 Mcu.IP6=TIM6 Mcu.IP7=USART1 Mcu.IPNb=8 Mcu.Name=STM32L431R(B-C)Tx Mcu.Package=LQFP64 Mcu.Pin0=PH0-OSC_IN (PH0) Mcu.Pin1=PH1-OSC_OUT (PH1) Mcu.Pin10=PA9 Mcu.Pin11=PA10 Mcu.Pin12=PA11 Mcu.Pin13=PD2 Mcu.Pin14=VP_SYS_VS_Systick Mcu.Pin15=VP_TIM6_VS_ClockSourceINT Mcu.Pin2=PB0 Mcu.Pin3=PB1 Mcu.Pin4=PB2 Mcu.Pin5=PB12 Mcu.Pin6=PB13 Mcu.Pin7=PB14 Mcu.Pin8=PC6 Mcu.Pin9=PC9 Mcu.PinsNb=16 Mcu.Pin10=PB14 Mcu.Pin11=PC6 Mcu.Pin12=PC9 Mcu.Pin13=PA9 Mcu.Pin14=PA10 Mcu.Pin15=PA11 Mcu.Pin16=PD2 Mcu.Pin17=VP_SYS_VS_Systick Mcu.Pin18=VP_TIM6_VS_ClockSourceINT Mcu.Pin2=PA5 Mcu.Pin3=PA6 Mcu.Pin4=PA7 Mcu.Pin5=PB0 Mcu.Pin6=PB1 Mcu.Pin7=PB2 Mcu.Pin8=PB12 Mcu.Pin9=PB13 Mcu.PinsNb=19 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32L431RCTx @@ -72,6 +76,13 @@ PA11.GPIO_PuPd=GPIO_PULLDOWN PA11.Locked=true PA11.Signal=S_TIM1_CH4 PA5.Locked=true PA5.Mode=Full_Duplex_Master PA5.Signal=SPI1_SCK PA6.Mode=Full_Duplex_Master PA6.Signal=SPI1_MISO PA7.Mode=Full_Duplex_Master PA7.Signal=SPI1_MOSI PA9.Mode=Asynchronous PA9.Signal=USART1_TX PB0.GPIOParameters=GPIO_Label @@ -206,6 +217,13 @@ SH.GPXTI14.ConfNb=1 SH.S_TIM1_CH4.0=TIM1_CH4,PWM Generation4 CH4 SH.S_TIM1_CH4.ConfNb=1 SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_4 SPI1.CalculateBaudRate=20.0 MBits/s SPI1.DataSize=SPI_DATASIZE_8BIT SPI1.Direction=SPI_DIRECTION_2LINES SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRatePrescaler SPI1.Mode=SPI_MODE_MASTER SPI1.VirtualType=VM_MASTER TIM1.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 TIM1.IPParameters=Channel-PWM Generation4 CH4,Prescaler,Period,Pulse-PWM Generation4 CH4 TIM1.Period=370-1