|
@@ -1,425 +1,425 @@
|
|
|
-#include "at32f403a_407.h"
|
|
|
-#include "spi_flash.h"
|
|
|
-#include "spi_common.h"
|
|
|
-#include "FreeRTOS.h"
|
|
|
-#include "task.h"
|
|
|
-#include "common_config.h"
|
|
|
-#include <string.h>
|
|
|
-#include <stdio.h>
|
|
|
-
|
|
|
-#define SPI_FLASH SPI3
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-#define INCLUDE_SPI_TEST 0
|
|
|
-
|
|
|
-//SemaphoreHandle_t spi_mutex;
|
|
|
-
|
|
|
-static uint8_t spi_tx_rx(uint8_t byte) {
|
|
|
- return common_spi_tx_rx(SPI_FLASH, byte);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-#define CMD_WREN 0x06 // +
|
|
|
-#define CMD_WRDI 0x04 // +
|
|
|
-#define CMD_WRSR 0x01 // +
|
|
|
-#define CMD_RDSR 0x05 // +
|
|
|
-#if defined (FLASH_TYPE_AT25SF161)
|
|
|
-#define CMD_READ 0x03 //0x0B // +
|
|
|
-#elif defined (FLASH_TYPE_MX25L1606E)
|
|
|
-#define CMD_READ 0x03 // +
|
|
|
-#endif
|
|
|
-#define CMD_SE 0x20 // + Block Erse 4 Kbytes
|
|
|
-#define CMD_BE 0x52 // Block Erase 32 Kbytes
|
|
|
-#define CMD_CE 0x60 // + Chip Erase
|
|
|
-#define CMD_PP 0x02 // + Byte/Page Program (1 to 256 Bytes)
|
|
|
-#define CMD_RDSFDP 0x5A // - not used for FLASH_TYPE_AT25SF161
|
|
|
-
|
|
|
-#define SR_WIP (1 << 0)
|
|
|
-#define SR_WEL (1 << 1)
|
|
|
-#define SR_SRWD (1 << 7)
|
|
|
-
|
|
|
-static spi_flash_desc_t spi_flash_desc;
|
|
|
-
|
|
|
-static inline void wait_write_enable(void) {
|
|
|
- uint8_t status;
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(CMD_RDSR);
|
|
|
- do {
|
|
|
- status = spi_tx_rx(0);
|
|
|
- } while (!(status & SR_WEL));
|
|
|
- SPI_FLASH_CS_H();
|
|
|
-}
|
|
|
-
|
|
|
-static inline void wait_write_end(void) {
|
|
|
- uint8_t status;
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(CMD_RDSR);
|
|
|
- do {
|
|
|
- status = spi_tx_rx(0);
|
|
|
- } while (status & SR_WIP);
|
|
|
- SPI_FLASH_CS_H();
|
|
|
-}
|
|
|
-
|
|
|
-static inline void send_addr(int addr) {
|
|
|
- spi_tx_rx((addr >> 16) & 0xFF);
|
|
|
- spi_tx_rx((addr >> 8) & 0xFF);
|
|
|
- spi_tx_rx(addr & 0xFF);
|
|
|
-}
|
|
|
-
|
|
|
-static int spi_flash_read_sfdp(int addr, void *buf, size_t len) {
|
|
|
- uint8_t *ptr = (uint8_t*)buf;
|
|
|
- //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(CMD_RDSFDP);
|
|
|
- send_addr(addr);
|
|
|
- spi_tx_rx(0);
|
|
|
- while (len--)
|
|
|
- *ptr++ = spi_tx_rx(0);
|
|
|
- SPI_FLASH_CS_H();
|
|
|
- //xSemaphoreGive(spi_mutex);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-ssize_t spi_flash_read(int addr, void *buf, size_t len, uint32_t timeout) {
|
|
|
- uint8_t *ptr = (uint8_t*)buf;
|
|
|
- (void)timeout;
|
|
|
- //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(CMD_READ);
|
|
|
- send_addr(addr);
|
|
|
- while (len--)
|
|
|
- *ptr++ = spi_tx_rx(0);
|
|
|
- SPI_FLASH_CS_H();
|
|
|
- //xSemaphoreGive(spi_mutex);
|
|
|
- return len;
|
|
|
-}
|
|
|
-
|
|
|
-#define TIMEOUT 10000
|
|
|
-
|
|
|
-uint16_t spi_flash_pp(int addr, const void *buf, size_t len, uint32_t timeout) {
|
|
|
- uint8_t *ptr = (uint8_t*)buf;
|
|
|
- (void)timeout;
|
|
|
- ssize_t ret = 0;
|
|
|
-
|
|
|
- if ((addr & 0xFF) + len > 0xFF)
|
|
|
- len = 0x100 - (addr & 0xFF);
|
|
|
- ret = len;
|
|
|
- //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(CMD_WREN);
|
|
|
- SPI_FLASH_CS_H();
|
|
|
-
|
|
|
- wait_write_enable();
|
|
|
-
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(CMD_PP);
|
|
|
- send_addr(addr);
|
|
|
- while (len--)
|
|
|
- spi_tx_rx(*ptr++);
|
|
|
- SPI_FLASH_CS_H();
|
|
|
-
|
|
|
- wait_write_end();
|
|
|
- //xSemaphoreGive(spi_mutex);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-ssize_t spi_flash_write(int addr, const void *buf, size_t len, uint32_t timeout) {
|
|
|
- (void)timeout;
|
|
|
- int ret = 0, offset = 0;
|
|
|
- do {
|
|
|
- ret = spi_flash_pp(addr + offset, (uint8_t*)buf + offset, len - offset, 0);
|
|
|
- offset += ret;
|
|
|
- } while (len - offset);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-int spi_flash_chip_erase(uint32_t timeout) {
|
|
|
- (void)timeout;
|
|
|
- //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(CMD_WREN);
|
|
|
- SPI_FLASH_CS_H();
|
|
|
- wait_write_enable();
|
|
|
-
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(CMD_CE);
|
|
|
- SPI_FLASH_CS_H();
|
|
|
-
|
|
|
- wait_write_end();
|
|
|
- //xSemaphoreGive(spi_mutex);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-int spi_flash_erase_sector(int addr, uint32_t timeout) {
|
|
|
- (void)timeout;
|
|
|
- //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(CMD_WREN);
|
|
|
- SPI_FLASH_CS_H();
|
|
|
-
|
|
|
- wait_write_enable();
|
|
|
-
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(CMD_SE);
|
|
|
- send_addr(addr);
|
|
|
- SPI_FLASH_CS_H();
|
|
|
-
|
|
|
- wait_write_end();
|
|
|
- //xSemaphoreGive(spi_mutex);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-unsigned int spi_flash_get_sector_size(void) {
|
|
|
- return spi_flash_desc.sector_size;
|
|
|
-}
|
|
|
-
|
|
|
-unsigned int spi_flash_get_sector_count(void) {
|
|
|
- return spi_flash_desc.sector_count;
|
|
|
-}
|
|
|
-
|
|
|
-unsigned int spi_flash_get_total_size(void) {
|
|
|
- return spi_flash_desc.sector_count * spi_flash_desc.sector_size;
|
|
|
-}
|
|
|
-
|
|
|
-bool spi_flash_is_init(void) {
|
|
|
- return spi_flash_desc.present;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-bool spi_flash_init(void)
|
|
|
-{
|
|
|
- bool ret = false;
|
|
|
- uint8_t tmp[4] = {0};
|
|
|
-
|
|
|
- SPI_FLASH_CS_H();
|
|
|
-
|
|
|
- spi_flash_get_id(tmp);
|
|
|
- if (!(tmp[0] == 0x1F && tmp[1] == 0x86 && tmp[2] == 0x01))
|
|
|
- {
|
|
|
- ret = false;
|
|
|
-
|
|
|
- spi_flash_read_sfdp(0, tmp, 4);
|
|
|
- if (!(tmp[0] == 0x53 && tmp[1] == 0x46 && tmp[2] == 0x44 && tmp[3] == 0x50))
|
|
|
- ret = false;
|
|
|
- else
|
|
|
- ret = true;
|
|
|
- }
|
|
|
- else
|
|
|
- ret = true;
|
|
|
-
|
|
|
- if (ret)
|
|
|
- {
|
|
|
- spi_flash_desc.sector_size = SPI_FLASH_SECTOR_SIZE;
|
|
|
- spi_flash_desc.sector_erase_op = 32;
|
|
|
- spi_flash_desc.sector_count = 512;
|
|
|
- spi_flash_desc.present = true;
|
|
|
- return true;
|
|
|
- }
|
|
|
- else
|
|
|
- return false;
|
|
|
-
|
|
|
-#if 0
|
|
|
-#if defined (FLASH_TYPE_AT25SF161)
|
|
|
-
|
|
|
- uint8_t tmp[4] = {0};
|
|
|
-
|
|
|
- SPI_FLASH_CS_H();
|
|
|
-
|
|
|
- spi_flash_get_id(tmp);
|
|
|
- if (!(tmp[0] == 0x1F && tmp[1] == 0x86 && tmp[2] == 0x01))
|
|
|
- return 0;
|
|
|
-
|
|
|
- spi_flash_desc.sector_size = SPI_FLASH_SECTOR_SIZE;
|
|
|
- spi_flash_desc.sector_erase_op = 32;
|
|
|
- spi_flash_desc.sector_count = 512;
|
|
|
- spi_flash_desc.present = true;
|
|
|
-
|
|
|
-
|
|
|
- return 1;
|
|
|
-
|
|
|
-#elif defined (FLASH_TYPE_MX25L1606E)
|
|
|
-
|
|
|
- uint32_t i, ptable, bitsize = 0;
|
|
|
- uint8_t tmp[4];
|
|
|
-
|
|
|
- spi_flash_desc.present = false;
|
|
|
-
|
|
|
- // check SFDP magic
|
|
|
-
|
|
|
- SPI_FLASH_CS_H();
|
|
|
-
|
|
|
- spi_flash_read_sfdp(0, tmp, 4);
|
|
|
- if (!(tmp[0] == 0x53 && tmp[1] == 0x46 &&
|
|
|
- tmp[2] == 0x44 && tmp[3] == 0x50))
|
|
|
- return 0;
|
|
|
-
|
|
|
- // get parameter headers count
|
|
|
- spi_flash_read_sfdp(0x06, tmp, 1);
|
|
|
-
|
|
|
- // find first jedec pheader (with ID == 0)
|
|
|
- for (ptable = 0x08, i = 0; i <= tmp[0]; i++, ptable += 8) {
|
|
|
- spi_flash_read_sfdp(ptable, tmp, 1);
|
|
|
- if (tmp[0] == 0)
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- // read ptable pointer from pheader
|
|
|
- spi_flash_read_sfdp(ptable + 4, &ptable, 3);
|
|
|
-
|
|
|
- // get flash density (size in bits)
|
|
|
- if (spi_flash_read_sfdp(ptable + 4, &bitsize, 4) < 0 || !bitsize)
|
|
|
- return 0;
|
|
|
-
|
|
|
- // find smallest available sector
|
|
|
- for (i = 0; i < 4; i++) {
|
|
|
- tmp[0] = 0;
|
|
|
- if (spi_flash_read_sfdp(ptable + 0x1C + i*2, &tmp, 2) >= 0 &&
|
|
|
- tmp[0]) {
|
|
|
- spi_flash_desc.sector_size = 1 << tmp[0];
|
|
|
- spi_flash_desc.sector_erase_op = tmp[1];
|
|
|
- spi_flash_desc.sector_count = (bitsize + 1) >> (3 + tmp[0]);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (!spi_flash_desc.sector_size)
|
|
|
- return 0;
|
|
|
-
|
|
|
- spi_flash_desc.present = true;
|
|
|
-
|
|
|
- return 1;
|
|
|
-
|
|
|
-#endif
|
|
|
- return 0;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/*
|
|
|
-bool spi_flash_init(void){
|
|
|
- //spi_init_();
|
|
|
- spi_flash_desc.sector_size = SPI_FLASH_SECTOR_SIZE;
|
|
|
- spi_flash_desc.sector_erase_op = 32;
|
|
|
- spi_flash_desc.sector_count = 512;
|
|
|
- spi_flash_desc.present = true;
|
|
|
-
|
|
|
- return 1;
|
|
|
-}
|
|
|
-*/
|
|
|
-
|
|
|
-/*
|
|
|
-void init_spi_mutex(void)
|
|
|
-{
|
|
|
- spi_mutex = xSemaphoreCreateMutex();
|
|
|
-}
|
|
|
-*/
|
|
|
-
|
|
|
-// -------------------------------------------------------------------------- //
|
|
|
-
|
|
|
-void spi_flash_get_id(uint8_t *buf)
|
|
|
-{
|
|
|
- //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
- SPI_FLASH_CS_L();
|
|
|
- spi_tx_rx(0x9F);
|
|
|
- *buf++ = spi_tx_rx(0);
|
|
|
- *buf++ = spi_tx_rx(0);
|
|
|
- *buf++ = spi_tx_rx(0);
|
|
|
-
|
|
|
- SPI_FLASH_CS_H();
|
|
|
- //xSemaphoreGive(spi_mutex);
|
|
|
-}
|
|
|
-
|
|
|
-// -------------------------------------------------------------------------- //
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-#if INCLUDE_SPI_TEST
|
|
|
-const uint8_t txbuf1[] = "This film came out on DVD yesterday and I rushed to buy it. \
|
|
|
- This version is the first to render all the detail and perfection \
|
|
|
- of Jack Cardiff's amazing compositions and brilliant, varied photography. \
|
|
|
- As a collection of memorable images, this film is better than any comparable \
|
|
|
- historical epic of the period and even gives GWTW a run for its money. \
|
|
|
- King Vidor's direction is a series of 'tableaux vivants' where the \
|
|
|
- characters are not posing but acting in a very natural, period-specific way. \
|
|
|
- I have never had a problem with this adaptation of Tolstoy's novel. \
|
|
|
- I think it is a wonderful introduction to the period and the novel and that \
|
|
|
- it is a very poetic, very original work in its own right. Henry Fonda's \
|
|
|
- characterization is especially moving, including great memorable interactions \
|
|
|
- with/reations to Mel Ferrer, Audrey Hepburn, Helmut Dantine and John Mills, but \
|
|
|
- all members of the cast are actually perfect. The harrowing last 45 minutes of \
|
|
|
- the film manage to convey a sense of history, a sense of grandeur as well as to \
|
|
|
- communicate very clearly Tolstoy's ideas about the meaning of life, by relying \
|
|
|
- mostly on the power of memorable images. The most conspicuous handicap of this movie, \
|
|
|
- in my opinion, is its soundtrack (in glorious mono). The barely hi-fi recording of \
|
|
|
- dialogues and music sounds pinched, hollow and tinny and it always has in very version \
|
|
|
- I have ever seen: in the theatres, on TV and on video. Even the soundtrack album is \
|
|
|
- an atrocity. In some scenes, before the necessary adjustments of bass and treble, \
|
|
|
- Audrey Hepburn's and Mel Ferrer's voices actually hurt your ear. Nino Rota's very \
|
|
|
- Russian-sounding score is serviceable and melodic, although rather sparse in its \
|
|
|
- orchestration and in the number of players. One can only wonder what 'War and Peace' \
|
|
|
- could have sounded like with a cohort of Hollywood arrangers, decent recording facilities \
|
|
|
- and lavish, varied orchestrations in true high fidelity and stereophonic sound. \
|
|
|
- According to Lukas Kendall of 'Film Score Monthly', the original recording elements \
|
|
|
- of the soundtrack have long ago disappeared, which is the common lot of international, \
|
|
|
- independent co-productions of the era. Someone somewhere is certainly guilty of \
|
|
|
- skimping on quality or embezzlement for this 1956 movie to sound so much worse \
|
|
|
- than a 1939, pre-hi-fi epic like GWTW. Like all VistaVision films, this one was \
|
|
|
- meant to be shown in Perspecta Stereophonic Sound where the mono dialog track was \
|
|
|
- meant to be channelled to three different directions, making it directional, while \
|
|
|
- the separate mono music + sound effects track was generally directed to all three \
|
|
|
- speakers at the same time. The results fooled the viewers into thinking everything \
|
|
|
- was in true stereo and the reproduction of the music was usually in very high fidelity. \
|
|
|
- Maybe the soundtrack used on the DVD is a mono reduction of those two separate tracks \
|
|
|
- that has squandered that fidelity and maybe the DVD can be issued again with better \
|
|
|
- results in some kind of 4.0 presentation. When they do, very little electronic \
|
|
|
- restoration work will be needed to make the image absolutely perfect. \
|
|
|
- But let's concentrate on the positive: This film is a summit of visual \
|
|
|
- splendour and its sets, costumes, colour photography, composition and lighting \
|
|
|
- achieve, in every single scene, wonders of artistry, creativity and delicacy \
|
|
|
- But let's concentrate on the positive: This film is a summit of visual \
|
|
|
- splendour and its sets, costumes, colour photography, composition and lighting \
|
|
|
- achieve, in every single scene, wonders of artistry, creativity and delicacy \
|
|
|
- that will probably never be equalled. Suffice it to say that it has, \
|
|
|
- among many other treasures, a sunrise duel scene in the snow that still has viewers \
|
|
|
- wondering whether it was shot outdoors or in a studio and that will have them wondering foreverhsgkhgkshgu.\r\n";
|
|
|
-
|
|
|
-
|
|
|
-#define countof(a) (sizeof(a) / sizeof(*(a)))
|
|
|
-#define bufsize1 (countof(txbuf1)-1)
|
|
|
-
|
|
|
-uint8_t rxbuf1[bufsize1] = {0};
|
|
|
-
|
|
|
-bool spi_flash_test(void) {
|
|
|
- if (!spi_flash_is_init()) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- const unsigned int sector_count = spi_flash_get_sector_count();
|
|
|
- const unsigned int sector_size = spi_flash_get_sector_size();
|
|
|
- const unsigned int total_size = spi_flash_get_total_size();
|
|
|
-
|
|
|
- printf("Present: %u sectors, %u bytes per sector (%u bytes total)\r\n",
|
|
|
- sector_count, sector_size, total_size);
|
|
|
-
|
|
|
- for (uint16_t i = 0; i < sector_count; i++) {
|
|
|
- printf("sector: %u/%u ", i, sector_count);
|
|
|
-
|
|
|
- spi_flash_erase_sector(i * sector_size, 0);
|
|
|
- spi_flash_write(i * sector_size, txbuf1, bufsize1, 0);
|
|
|
-
|
|
|
- memset(rxbuf1, 0, bufsize1);
|
|
|
- spi_flash_read(i * sector_size, rxbuf1, bufsize1, 0);
|
|
|
-
|
|
|
- if (memcmp(txbuf1, rxbuf1, bufsize1) != 0) {
|
|
|
- printf("fail\r\n");
|
|
|
- return false;
|
|
|
- }
|
|
|
- printf("ok\r\n");
|
|
|
- }
|
|
|
- printf("\r\nDone\r\n");
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
+#include "at32f403a_407.h"
|
|
|
+#include "spi_flash.h"
|
|
|
+#include "spi_common.h"
|
|
|
+#include "FreeRTOS.h"
|
|
|
+#include "task.h"
|
|
|
+#include "common_config.h"
|
|
|
+#include <string.h>
|
|
|
+#include <stdio.h>
|
|
|
+
|
|
|
+#define SPI_FLASH SPI3
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#define INCLUDE_SPI_TEST 0
|
|
|
+
|
|
|
+//SemaphoreHandle_t spi_mutex;
|
|
|
+
|
|
|
+static uint8_t spi_tx_rx(uint8_t byte) {
|
|
|
+ return common_spi_tx_rx(SPI_FLASH, byte);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#define CMD_WREN 0x06 // +
|
|
|
+#define CMD_WRDI 0x04 // +
|
|
|
+#define CMD_WRSR 0x01 // +
|
|
|
+#define CMD_RDSR 0x05 // +
|
|
|
+#if defined (FLASH_TYPE_AT25SF161)
|
|
|
+#define CMD_READ 0x03 //0x0B // +
|
|
|
+#elif defined (FLASH_TYPE_MX25L1606E)
|
|
|
+#define CMD_READ 0x03 // +
|
|
|
+#endif
|
|
|
+#define CMD_SE 0x20 // + Block Erse 4 Kbytes
|
|
|
+#define CMD_BE 0x52 // Block Erase 32 Kbytes
|
|
|
+#define CMD_CE 0x60 // + Chip Erase
|
|
|
+#define CMD_PP 0x02 // + Byte/Page Program (1 to 256 Bytes)
|
|
|
+#define CMD_RDSFDP 0x5A // - not used for FLASH_TYPE_AT25SF161
|
|
|
+
|
|
|
+#define SR_WIP (1 << 0)
|
|
|
+#define SR_WEL (1 << 1)
|
|
|
+#define SR_SRWD (1 << 7)
|
|
|
+
|
|
|
+static spi_flash_desc_t spi_flash_desc;
|
|
|
+
|
|
|
+static inline void wait_write_enable(void) {
|
|
|
+ uint8_t status;
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(CMD_RDSR);
|
|
|
+ do {
|
|
|
+ status = spi_tx_rx(0);
|
|
|
+ } while (!(status & SR_WEL));
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+}
|
|
|
+
|
|
|
+static inline void wait_write_end(void) {
|
|
|
+ uint8_t status;
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(CMD_RDSR);
|
|
|
+ do {
|
|
|
+ status = spi_tx_rx(0);
|
|
|
+ } while (status & SR_WIP);
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+}
|
|
|
+
|
|
|
+static inline void send_addr(int addr) {
|
|
|
+ spi_tx_rx((addr >> 16) & 0xFF);
|
|
|
+ spi_tx_rx((addr >> 8) & 0xFF);
|
|
|
+ spi_tx_rx(addr & 0xFF);
|
|
|
+}
|
|
|
+
|
|
|
+static int spi_flash_read_sfdp(int addr, void *buf, size_t len) {
|
|
|
+ uint8_t *ptr = (uint8_t*)buf;
|
|
|
+ //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(CMD_RDSFDP);
|
|
|
+ send_addr(addr);
|
|
|
+ spi_tx_rx(0);
|
|
|
+ while (len--)
|
|
|
+ *ptr++ = spi_tx_rx(0);
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+ //xSemaphoreGive(spi_mutex);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+ssize_t spi_flash_read(int addr, void *buf, size_t len, uint32_t timeout) {
|
|
|
+ uint8_t *ptr = (uint8_t*)buf;
|
|
|
+ (void)timeout;
|
|
|
+ //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(CMD_READ);
|
|
|
+ send_addr(addr);
|
|
|
+ while (len--)
|
|
|
+ *ptr++ = spi_tx_rx(0);
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+ //xSemaphoreGive(spi_mutex);
|
|
|
+ return len;
|
|
|
+}
|
|
|
+
|
|
|
+#define TIMEOUT 10000
|
|
|
+
|
|
|
+uint16_t spi_flash_pp(int addr, const void *buf, size_t len, uint32_t timeout) {
|
|
|
+ uint8_t *ptr = (uint8_t*)buf;
|
|
|
+ (void)timeout;
|
|
|
+ ssize_t ret = 0;
|
|
|
+
|
|
|
+ if ((addr & 0xFF) + len > 0xFF)
|
|
|
+ len = 0x100 - (addr & 0xFF);
|
|
|
+ ret = len;
|
|
|
+ //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(CMD_WREN);
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+
|
|
|
+ wait_write_enable();
|
|
|
+
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(CMD_PP);
|
|
|
+ send_addr(addr);
|
|
|
+ while (len--)
|
|
|
+ spi_tx_rx(*ptr++);
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+
|
|
|
+ wait_write_end();
|
|
|
+ //xSemaphoreGive(spi_mutex);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+ssize_t spi_flash_write(int addr, const void *buf, size_t len, uint32_t timeout) {
|
|
|
+ (void)timeout;
|
|
|
+ int ret = 0, offset = 0;
|
|
|
+ do {
|
|
|
+ ret = spi_flash_pp(addr + offset, (uint8_t*)buf + offset, len - offset, 0);
|
|
|
+ offset += ret;
|
|
|
+ } while (len - offset);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int spi_flash_chip_erase(uint32_t timeout) {
|
|
|
+ (void)timeout;
|
|
|
+ //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(CMD_WREN);
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+ wait_write_enable();
|
|
|
+
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(CMD_CE);
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+
|
|
|
+ wait_write_end();
|
|
|
+ //xSemaphoreGive(spi_mutex);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int spi_flash_erase_sector(int addr, uint32_t timeout) {
|
|
|
+ (void)timeout;
|
|
|
+ //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(CMD_WREN);
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+
|
|
|
+ wait_write_enable();
|
|
|
+
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(CMD_SE);
|
|
|
+ send_addr(addr);
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+
|
|
|
+ wait_write_end();
|
|
|
+ //xSemaphoreGive(spi_mutex);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int spi_flash_get_sector_size(void) {
|
|
|
+ return spi_flash_desc.sector_size;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int spi_flash_get_sector_count(void) {
|
|
|
+ return spi_flash_desc.sector_count;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int spi_flash_get_total_size(void) {
|
|
|
+ return spi_flash_desc.sector_count * spi_flash_desc.sector_size;
|
|
|
+}
|
|
|
+
|
|
|
+bool spi_flash_is_init(void) {
|
|
|
+ return spi_flash_desc.present;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+bool spi_flash_init(void)
|
|
|
+{
|
|
|
+ bool ret = false;
|
|
|
+ uint8_t tmp[4] = {0};
|
|
|
+
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+
|
|
|
+ spi_flash_get_id(tmp);
|
|
|
+ if (!(tmp[0] == 0x1F && tmp[1] == 0x86 && tmp[2] == 0x01))
|
|
|
+ {
|
|
|
+ ret = false;
|
|
|
+
|
|
|
+ spi_flash_read_sfdp(0, tmp, 4);
|
|
|
+ if (!(tmp[0] == 0x53 && tmp[1] == 0x46 && tmp[2] == 0x44 && tmp[3] == 0x50))
|
|
|
+ ret = false;
|
|
|
+ else
|
|
|
+ ret = true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ ret = true;
|
|
|
+
|
|
|
+ if (ret)
|
|
|
+ {
|
|
|
+ spi_flash_desc.sector_size = SPI_FLASH_SECTOR_SIZE;
|
|
|
+ spi_flash_desc.sector_erase_op = 32;
|
|
|
+ spi_flash_desc.sector_count = 512;
|
|
|
+ spi_flash_desc.present = true;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return false;
|
|
|
+
|
|
|
+#if 0
|
|
|
+#if defined (FLASH_TYPE_AT25SF161)
|
|
|
+
|
|
|
+ uint8_t tmp[4] = {0};
|
|
|
+
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+
|
|
|
+ spi_flash_get_id(tmp);
|
|
|
+ if (!(tmp[0] == 0x1F && tmp[1] == 0x86 && tmp[2] == 0x01))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ spi_flash_desc.sector_size = SPI_FLASH_SECTOR_SIZE;
|
|
|
+ spi_flash_desc.sector_erase_op = 32;
|
|
|
+ spi_flash_desc.sector_count = 512;
|
|
|
+ spi_flash_desc.present = true;
|
|
|
+
|
|
|
+
|
|
|
+ return 1;
|
|
|
+
|
|
|
+#elif defined (FLASH_TYPE_MX25L1606E)
|
|
|
+
|
|
|
+ uint32_t i, ptable, bitsize = 0;
|
|
|
+ uint8_t tmp[4];
|
|
|
+
|
|
|
+ spi_flash_desc.present = false;
|
|
|
+
|
|
|
+ // check SFDP magic
|
|
|
+
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+
|
|
|
+ spi_flash_read_sfdp(0, tmp, 4);
|
|
|
+ if (!(tmp[0] == 0x53 && tmp[1] == 0x46 &&
|
|
|
+ tmp[2] == 0x44 && tmp[3] == 0x50))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ // get parameter headers count
|
|
|
+ spi_flash_read_sfdp(0x06, tmp, 1);
|
|
|
+
|
|
|
+ // find first jedec pheader (with ID == 0)
|
|
|
+ for (ptable = 0x08, i = 0; i <= tmp[0]; i++, ptable += 8) {
|
|
|
+ spi_flash_read_sfdp(ptable, tmp, 1);
|
|
|
+ if (tmp[0] == 0)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // read ptable pointer from pheader
|
|
|
+ spi_flash_read_sfdp(ptable + 4, &ptable, 3);
|
|
|
+
|
|
|
+ // get flash density (size in bits)
|
|
|
+ if (spi_flash_read_sfdp(ptable + 4, &bitsize, 4) < 0 || !bitsize)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ // find smallest available sector
|
|
|
+ for (i = 0; i < 4; i++) {
|
|
|
+ tmp[0] = 0;
|
|
|
+ if (spi_flash_read_sfdp(ptable + 0x1C + i*2, &tmp, 2) >= 0 &&
|
|
|
+ tmp[0]) {
|
|
|
+ spi_flash_desc.sector_size = 1 << tmp[0];
|
|
|
+ spi_flash_desc.sector_erase_op = tmp[1];
|
|
|
+ spi_flash_desc.sector_count = (bitsize + 1) >> (3 + tmp[0]);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!spi_flash_desc.sector_size)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ spi_flash_desc.present = true;
|
|
|
+
|
|
|
+ return 1;
|
|
|
+
|
|
|
+#endif
|
|
|
+ return 0;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+bool spi_flash_init(void){
|
|
|
+ //spi_init_();
|
|
|
+ spi_flash_desc.sector_size = SPI_FLASH_SECTOR_SIZE;
|
|
|
+ spi_flash_desc.sector_erase_op = 32;
|
|
|
+ spi_flash_desc.sector_count = 512;
|
|
|
+ spi_flash_desc.present = true;
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+*/
|
|
|
+
|
|
|
+/*
|
|
|
+void init_spi_mutex(void)
|
|
|
+{
|
|
|
+ spi_mutex = xSemaphoreCreateMutex();
|
|
|
+}
|
|
|
+*/
|
|
|
+
|
|
|
+// -------------------------------------------------------------------------- //
|
|
|
+
|
|
|
+void spi_flash_get_id(uint8_t *buf)
|
|
|
+{
|
|
|
+ //xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
+ SPI_FLASH_CS_L();
|
|
|
+ spi_tx_rx(0x9F);
|
|
|
+ *buf++ = spi_tx_rx(0);
|
|
|
+ *buf++ = spi_tx_rx(0);
|
|
|
+ *buf++ = spi_tx_rx(0);
|
|
|
+
|
|
|
+ SPI_FLASH_CS_H();
|
|
|
+ //xSemaphoreGive(spi_mutex);
|
|
|
+}
|
|
|
+
|
|
|
+// -------------------------------------------------------------------------- //
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#if INCLUDE_SPI_TEST
|
|
|
+const uint8_t txbuf1[] = "This film came out on DVD yesterday and I rushed to buy it. \
|
|
|
+ This version is the first to render all the detail and perfection \
|
|
|
+ of Jack Cardiff's amazing compositions and brilliant, varied photography. \
|
|
|
+ As a collection of memorable images, this film is better than any comparable \
|
|
|
+ historical epic of the period and even gives GWTW a run for its money. \
|
|
|
+ King Vidor's direction is a series of 'tableaux vivants' where the \
|
|
|
+ characters are not posing but acting in a very natural, period-specific way. \
|
|
|
+ I have never had a problem with this adaptation of Tolstoy's novel. \
|
|
|
+ I think it is a wonderful introduction to the period and the novel and that \
|
|
|
+ it is a very poetic, very original work in its own right. Henry Fonda's \
|
|
|
+ characterization is especially moving, including great memorable interactions \
|
|
|
+ with/reations to Mel Ferrer, Audrey Hepburn, Helmut Dantine and John Mills, but \
|
|
|
+ all members of the cast are actually perfect. The harrowing last 45 minutes of \
|
|
|
+ the film manage to convey a sense of history, a sense of grandeur as well as to \
|
|
|
+ communicate very clearly Tolstoy's ideas about the meaning of life, by relying \
|
|
|
+ mostly on the power of memorable images. The most conspicuous handicap of this movie, \
|
|
|
+ in my opinion, is its soundtrack (in glorious mono). The barely hi-fi recording of \
|
|
|
+ dialogues and music sounds pinched, hollow and tinny and it always has in very version \
|
|
|
+ I have ever seen: in the theatres, on TV and on video. Even the soundtrack album is \
|
|
|
+ an atrocity. In some scenes, before the necessary adjustments of bass and treble, \
|
|
|
+ Audrey Hepburn's and Mel Ferrer's voices actually hurt your ear. Nino Rota's very \
|
|
|
+ Russian-sounding score is serviceable and melodic, although rather sparse in its \
|
|
|
+ orchestration and in the number of players. One can only wonder what 'War and Peace' \
|
|
|
+ could have sounded like with a cohort of Hollywood arrangers, decent recording facilities \
|
|
|
+ and lavish, varied orchestrations in true high fidelity and stereophonic sound. \
|
|
|
+ According to Lukas Kendall of 'Film Score Monthly', the original recording elements \
|
|
|
+ of the soundtrack have long ago disappeared, which is the common lot of international, \
|
|
|
+ independent co-productions of the era. Someone somewhere is certainly guilty of \
|
|
|
+ skimping on quality or embezzlement for this 1956 movie to sound so much worse \
|
|
|
+ than a 1939, pre-hi-fi epic like GWTW. Like all VistaVision films, this one was \
|
|
|
+ meant to be shown in Perspecta Stereophonic Sound where the mono dialog track was \
|
|
|
+ meant to be channelled to three different directions, making it directional, while \
|
|
|
+ the separate mono music + sound effects track was generally directed to all three \
|
|
|
+ speakers at the same time. The results fooled the viewers into thinking everything \
|
|
|
+ was in true stereo and the reproduction of the music was usually in very high fidelity. \
|
|
|
+ Maybe the soundtrack used on the DVD is a mono reduction of those two separate tracks \
|
|
|
+ that has squandered that fidelity and maybe the DVD can be issued again with better \
|
|
|
+ results in some kind of 4.0 presentation. When they do, very little electronic \
|
|
|
+ restoration work will be needed to make the image absolutely perfect. \
|
|
|
+ But let's concentrate on the positive: This film is a summit of visual \
|
|
|
+ splendour and its sets, costumes, colour photography, composition and lighting \
|
|
|
+ achieve, in every single scene, wonders of artistry, creativity and delicacy \
|
|
|
+ But let's concentrate on the positive: This film is a summit of visual \
|
|
|
+ splendour and its sets, costumes, colour photography, composition and lighting \
|
|
|
+ achieve, in every single scene, wonders of artistry, creativity and delicacy \
|
|
|
+ that will probably never be equalled. Suffice it to say that it has, \
|
|
|
+ among many other treasures, a sunrise duel scene in the snow that still has viewers \
|
|
|
+ wondering whether it was shot outdoors or in a studio and that will have them wondering foreverhsgkhgkshgu.\r\n";
|
|
|
+
|
|
|
+
|
|
|
+#define countof(a) (sizeof(a) / sizeof(*(a)))
|
|
|
+#define bufsize1 (countof(txbuf1)-1)
|
|
|
+
|
|
|
+uint8_t rxbuf1[bufsize1] = {0};
|
|
|
+
|
|
|
+bool spi_flash_test(void) {
|
|
|
+ if (!spi_flash_is_init()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ const unsigned int sector_count = spi_flash_get_sector_count();
|
|
|
+ const unsigned int sector_size = spi_flash_get_sector_size();
|
|
|
+ const unsigned int total_size = spi_flash_get_total_size();
|
|
|
+
|
|
|
+ printf("Present: %u sectors, %u bytes per sector (%u bytes total)\r\n",
|
|
|
+ sector_count, sector_size, total_size);
|
|
|
+
|
|
|
+ for (uint16_t i = 0; i < sector_count; i++) {
|
|
|
+ printf("sector: %u/%u ", i, sector_count);
|
|
|
+
|
|
|
+ spi_flash_erase_sector(i * sector_size, 0);
|
|
|
+ spi_flash_write(i * sector_size, txbuf1, bufsize1, 0);
|
|
|
+
|
|
|
+ memset(rxbuf1, 0, bufsize1);
|
|
|
+ spi_flash_read(i * sector_size, rxbuf1, bufsize1, 0);
|
|
|
+
|
|
|
+ if (memcmp(txbuf1, rxbuf1, bufsize1) != 0) {
|
|
|
+ printf("fail\r\n");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ printf("ok\r\n");
|
|
|
+ }
|
|
|
+ printf("\r\nDone\r\n");
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
#endif
|