| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- #include "at45db041.h"
- #include "periph.h"
- #include <memory.h>
- #include <stdio.h>
- /*Make the buffer visible for the external flash*/
- extern uint8_t SPI_REC_BUF[512];
- /*Information structure*/
- at45db_t AT45DB;
- /**
- * @brief Initialize the external flash, with basic parameters and checks its availability.
- * @retval None.
- */
- void at45db_init()
- {
- memset(&AT45DB, 0, sizeof(AT45DB));
- uint16_t res = -1;
- uint8_t status_register[2] = {0};
- /*Check if the external flash memory is accessible*/
- res = at45db_read_man_id();
- printf("device.man.id: 0x%02X\r\n", res);
- if (!res)
- {
- /*External flash memory is not accessible*/
- printf("Unable to communicate with external flash. Initiate wake up process!\r\n");
- /*Wake up process*/
- res = at45db_wake_up_from_deep_sleep(AT45DB);
- if (!res)
- {
- /*Device could be in ultra deep sleep*/
- res = at45db_wake_up_from_ultra_deep_sleep(AT45DB);
- if (!res)
- {
- printf("Cannot wake up the external flash from ultra deep sleep\r\n");
- }
- else if (res)
- {
- printf("External flash memory woke up from ultra deep sleep\r\n");
- }
- }
- else if (res)
- {
- printf("External flash memory wake up from power down mode\r\n");
- }
- }
- else if (res)
- {
- printf("Correct device ID, external flash memory is accessible\r\n");
- }
- HAL_Delay(100);
- /*Initializa information structure*/
- #ifdef BINARY_PAGE_SIZE
- AT45DB.block_size = 2048;
- AT45DB.blocks = 256;
- AT45DB.flash_mbit = 4;
- AT45DB.page_size = 256;
- #endif
- #ifdef DATAFLASH_PAGE_SIZE
- AT45DB.block_size = 2112;
- AT45DB.blocks = 256;
- AT45DB.flash_mbit = 4;
- AT45DB.page_size = 264;
- #endif
- }
- /**
- * @brief Считывает один байт статус-регистра AT45DB041E.
- * @retval 1 байт статуса.
- *
- * Бит 7 (0x80) — RDY/BUSY: 1 = готов, 0 = занят
- * Бит 0 (0x01) — Page Size: 1 = binary (256 байт), 0 = standard (264 байта)
- */
- uint8_t at45db_get_status(void)
- {
- uint8_t cmd = STATUS_REGISTER;
- uint8_t status = 0;
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, &cmd, 1, HAL_MAX_DELAY);
- HAL_SPI_Receive(&hspi2, &status, 1, HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- return status;
- }
- /**
- * @brief Читает Manufacturer + Device ID.
- * @retval DEV_ID_OK или DEV_ID_ERROR.
- */
- dev_id_t at45db_read_man_id(void)
- {
- uint8_t opcode = MAN_ID_OPCD;
- uint8_t rec_buf[4] = {0};
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
- HAL_SPI_Receive(&hspi2, rec_buf, 4, HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- if (rec_buf[0] != 0x1F || rec_buf[1] != 0x24)
- return DEV_ID_ERROR;
- return DEV_ID_OK;
- }
- /**
- * @brief Проверяет текущий режим размера страницы.
- * @retval 256 если включён binary mode, 264 — если стандартный.
- */
- uint16_t at45db_get_page_size(void)
- {
- return (at45db_get_status() & 0x01) ? 256 : 264;
- }
- /**
- * @brief Проверяет, готов ли чип к новой операции.
- * @retval 1 — готов, 0 — занят.
- */
- int at45db_is_ready(void)
- {
- return (at45db_get_status() & 0x80) ? 1 : 0;
- }
- /**
- * @brief Wakes up external flash from deep sleep mode.
- * @param info : Structure information about the external flash operation.
- * @retval 1 for success, 0 on failure.
- */
- uint16_t at45db_wake_up_from_deep_sleep(at45db_t info)
- {
- uint16_t res = -1;
- uint8_t cmd = WAKE_UP_DEEP_SLEEP;
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, &cmd, 1, HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- // TODO: fix
- /*Return the MISO pin to its initial state*/
- // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2+1)));
- // CLEAR_BIT(GPIO_SPIx->MODER, (1U<<SPIx_GPIO_MISO_PIN*2));
- /*Read MAN-ID*/
- res = at45db_read_man_id();
- if (!res)
- {
- return 0;
- }
- info.state = _NORMAL_MODE;
- return 1;
- }
- /**
- * @brief Exit from ultra deep sleep.
- * @param info : Structure information about the external flash operation.
- * @retval 1 for success, 0 on failure.
- */
- uint16_t at45db_wake_up_from_ultra_deep_sleep(at45db_t info)
- {
- uint16_t res = -1;
- /*Select the device*/
- FLASH_CS_ENABLE();
- HAL_Delay(2);
- /*Release the device*/
- FLASH_CS_DISABLE();
- // TODO: fix
- /*Return the MISO pin to its initial state*/
- // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2+1)));
- // CLEAR_BIT(GPIO_SPIx->MODER, (1U<<SPIx_GPIO_MISO_PIN*2));
- /*Try to read MAD-ID*/
- res = at45db_read_man_id();
- if (!res)
- {
- /*Failure*/
- return 0;
- }
- /*Success*/
- info.state = _NORMAL_MODE;
- return 1;
- }
- void at45db_read(uint16_t page, uint8_t *data, uint16_t size)
- {
- uint8_t cmd[5];
- uint32_t addr = (uint32_t)page << 8;
- cmd[0] = 0x0B; // high-speed read
- cmd[1] = (addr >> 16) & 0xFF;
- cmd[2] = (addr >> 8) & 0xFF;
- cmd[3] = addr & 0xFF;
- cmd[4] = 0x00; // dummy
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, cmd, 5, HAL_MAX_DELAY);
- HAL_SPI_Receive(&hspi2, data, size, HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- }
- /**
- * @brief Enter flash into ultra deep sleep.
- * @param info : Structure information about the external flash operation.
- * @retval None.
- */
- void at45db_ultra_deep_sleep(at45db_t info)
- {
- uint8_t opcode = ULTRA_DEEP_SLEEP;
- /*Select the slave device*/
- FLASH_CS_ENABLE();
- /*Transmit the proper opcode*/
- HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
- /*Give some time to the system*/
- HAL_Delay(100);
- /*Release the device*/
- FLASH_CS_DISABLE();
- // TODO: fix
- /*Make the MISO pin analog, for power saving*/
- // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2+1)));
- // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2)));
- info.state = _U_DEEP_SLEEP;
- }
- void at45db_write(uint16_t page, uint8_t *data, uint16_t size)
- {
- uint8_t cmd[4];
- uint32_t addr = (uint32_t)page << 8;
- // 1. Запись во внутренний буфер
- cmd[0] = 0x84; cmd[1] = 0; cmd[2] = 0; cmd[3] = 0;
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, cmd, 4, HAL_MAX_DELAY);
- HAL_SPI_Transmit(&hspi2, data, size, HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- // 2. Перенос буфера в нужную страницу
- cmd[0] = 0x83;
- cmd[1] = (addr >> 16) & 0xFF;
- cmd[2] = (addr >> 8) & 0xFF;
- cmd[3] = addr & 0xFF;
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, cmd, 4, HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- }
- void at45db_read_continuous(uint32_t addr, uint8_t *buffer, uint32_t size)
- {
- uint8_t cmd[8];
- /*Preparing the command*/
- cmd[0] = 0xE8; //Opcode
- cmd[1] = (addr >> 16) & 0xFF; // Address byte 1
- cmd[2] = (addr >> 8) & 0xFF; // Address byte 2
- cmd[3] = addr & 0xFF; // Address byte 3
- cmd[4] = 0x00; // Dummy byte 1
- cmd[5] = 0x00; // Dummy byte 2
- cmd[6] = 0x00; // Dummy byte 3
- cmd[7] = 0x00; // Dummy byte 4
- /*Select the external flash memory*/
- FLASH_CS_ENABLE();
- /*Send the proper commands to load data to the internal buffer 1*/
- HAL_SPI_Transmit(&hspi2, cmd, sizeof(cmd), HAL_MAX_DELAY);
- /*Receive the data*/
- HAL_SPI_Receive(&hspi2, buffer, size, HAL_MAX_DELAY);
- /*Deselect the external flash memory*/
- FLASH_CS_DISABLE();
- }
- /**
- * @brief Configure page size. Careful you only have 10000 times to do that.
- * @param mode : Set 1 for DataFlash (264 bytes), 2 for Binary (256 bytes).
- * @retval None.
- */
- void at45db_page_size_conf(uint16_t mode)
- {
- uint8_t cmd[4] = {0};
- cmd[0] = 0x3D;
- cmd[1] = 0x2A;
- cmd[2] = 0x80;
- /*Check user input*/
- if (mode == 1)
- {
- /*Data flash page size*/
- cmd[3] = 0xA7;
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, cmd, sizeof(cmd), HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- }
- else if (mode == 2)
- {
- /*Binary page size*/
- cmd[3] = 0xA6;
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, cmd, sizeof(cmd), HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- }
- }
- /**
- * @brief Perform chip erase. This command erase the entire main memory.
- * @retval None.
- */
- void at45db_chip_erase(void)
- {
- uint8_t cmd[4] = {0};
- int res = -1;
- cmd[0] = CHIP_ERASE_1;
- cmd[1] = CHIP_ERASE_2;
- cmd[2] = CHIP_ERASE_3;
- cmd[3] = CHIP_ERASE_4;
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, cmd, 4, HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- /*Check for fault operation*/
- res = at45db_fault_check();
- if (res == 1) {
- printf("There was a fault in erase operation...\n\r");
- }
- else if (res == 0) {
- printf("Successful, erase operation...\n\r");
- }
- }
- /**
- * @brief Checks if a fault erased after an erase or program operation.
- * @retval 1 if an error is detected, 0 otherwise.
- */
- uint16_t at45db_fault_check(void)
- {
- uint8_t status_register[2];
- uint8_t opcode = STATUS_REGISTER;
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
- HAL_SPI_Receive(&hspi2, status_register, 2, HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- /*Check the 5th bit of the second byte EPE bit*/
- if ((status_register[1] & EPE_BIT)) {
- /*Error detected*/
- return 1;
- }
- /*Success, in erasing external flash memory*/
- return 0;
- }
- /**
- * @brief This function erases a sector inside the external memory.
- * @param sector_num : This is the number of the sector you need to erase.
- * @retval None.
- */
- void at45db_sector_erase(uint8_t sector_num)
- {
- uint8_t opcode = SECTOR_ERASE;
- uint8_t address_byte[3];
- address_byte[0] = ((sector_num) << 3) & 0xF8;
- address_byte[1] = 0x00;
- address_byte[2] = 0x00;
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
- HAL_SPI_Transmit(&hspi2, address_byte, 3, HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- }
- /**
- * @brief Erases a specific page inside the main memory.
- * @reval None.
- */
- void at45db_page_erase(uint16_t page)
- {
- uint8_t cmd[3] = {0};
- uint8_t opcode = PAGE_ERASE_CMD;
- page = page << 9;
- FLASH_CS_ENABLE();
- HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
- /*Modify the proper data bits*/
- cmd[0] = (page >> 16) & 0xFF;
- cmd[1] = (page >> 8) & 0xFF;
- cmd[2] = page & 0xFF;
- HAL_SPI_Transmit(&hspi2, cmd, 3, HAL_MAX_DELAY);
- FLASH_CS_DISABLE();
- }
- /**
- * @brief Enter flash into deep sleep mode.
- * @param info : Structure information about the external flash operation.
- * @retval None.
- */
- void at45db_deep_sleep(at45db_t *info)
- {
- uint8_t opcode = DEEP_SLEEP;
- /*Select the device*/
- FLASH_CS_ENABLE();
- /*Transmit the command the external FLASH memory*/
- HAL_SPI_Transmit(&hspi2, &opcode, 1, HAL_MAX_DELAY);
- /*Give some time to process*/
- HAL_Delay(100);
- /*Release the slave device*/
- FLASH_CS_DISABLE();
- /*Give some time to the system*/
- HAL_Delay(2);
- //TODO: fix
- /*Make the MISO pin analog, for power saving*/
- // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2+1)));
- // SET_BIT(GPIO_SPIx->MODER, (1U<<(SPIx_GPIO_MISO_PIN*2)));
- }
- void at45db_wait_ready(void)
- {
- while (!(at45db_get_status() & 0x80)) {
- HAL_Delay(1);
- }
- }
|