123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- #include "stm32f4xx_conf.h"
- #include "stm32f4xx.h"
- #include "spi_flash.h"
- #include "gpio.h"
- /*
- struct {
- uint8_t *tx;
- uint8_t *rx;
- uint16_t tx_len;
- uint16_t rx_len;
- uint8_t rx_skip;
- TN_SEM ready;
- TN_MUTEX busy;
- } xact;
- void SPI2_IRQHandler(void) {
- uint32_t status = SPI2->SR;
- uint8_t b;
- if (!xact.tx_len && !xact.rx_len) {
- SPI2->CR1 &= ~SPI_CR1_SPE;
- SPI2->CR2 &= ~(SPI_CR2_TXEIE | SPI_CR2_RXNEIE);
- tn_sem_isignal(&xact.ready);
- return;
- }
- if (status & SPI_SR_RXNE) {
- b = SPI2->DR;
- if (!xact.tx_len) {
- if (xact.rx_skip) {
- xact.rx_skip--;
- }
- else if (xact.rx_len) {
- *(xact.rx++) = b;
- xact.rx_len--;
- }
- }
- }
- if (status & SPI_SR_TXE) {
- if (xact.tx_len) { // have smth for tx
- SPI2->DR = *(xact.tx++);
- xact.tx_len--;
- }
- else if (xact.rx_len) {
- SPI2->DR = 0;
- }
- }
- }
- */
- #define SPI_FLASH_CS_L() gpio_set(SPI2_NSS, 0)
- #define SPI_FLASH_CS_H() gpio_set(SPI2_NSS, 1)
- //static TN_MUTEX spi_mutex;
- static uint8_t spi_tx_rx(uint8_t byte) {
- while (!(SPI2->SR & SPI_SR_TXE)) {}
- SPI2->DR = byte;
-
- while (!(SPI2->SR & SPI_SR_RXNE)) {}
- return SPI2->DR;
- }
- static void spi_cs_up(void) {
- SPI2->CR1 &= ~SPI_CR1_SPE;
- // GPIOB->BSRR = 1 << 12;
- }
- static void spi_cs_down(void) {
- // GPIOB->BRR = 1 << 12;
- SPI2->CR1 |= SPI_CR1_SPE;
- }
- static void spi_init_(void) {
- // tn_mutex_create(&spi_mutex, TN_MUTEX_ATTR_INHERIT, 0);
- //tn_sem_create(&xact.ready, 0, 1);
- RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
- RCC->APB1RSTR |= RCC_APB1RSTR_SPI2RST;
- RCC->APB1RSTR &= ~RCC_APB1RSTR_SPI2RST;
- SPI2->CR1 &= ~SPI_CR1_SPE;
- //SPI2->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1 | SPI_CR1_SSM | SPI_CR1_SSI;
- SPI2->CR1 = SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SSI;
- SPI2->CR2 = 0;//SPI_CR2_SSOE;
- SPI2->CR1 |= SPI_CR1_SPE;
- }
- #define CMD_WREN 0x06
- #define CMD_WRDI 0x04
- #define CMD_WRSR 0x01
- #define CMD_RDSR 0x05
- #define CMD_READ 0x03
- #define CMD_SE 0x20
- #define CMD_BE 0x52
- #define CMD_CE 0x60
- #define CMD_PP 0x02
- #define CMD_RDSFDP 0x5A
- #define SR_WIP (1 << 0)
- #define SR_WEL (1 << 1)
- #define SR_SRWD (1 << 7)
- spi_flash_desc_t spi_flash_desc;
- static inline void wait_write_enable(void) {
- uint8_t status;
- // spi_cs_down();
- SPI_FLASH_CS_L();
- spi_tx_rx(CMD_RDSR);
- do {
- status = spi_tx_rx(0);
- } while (!(status & SR_WEL));
- // spi_cs_up();
- 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* foo = (uint8_t *)buf;
- SPI_FLASH_CS_L();
- spi_tx_rx(CMD_RDSFDP);
- send_addr(addr);
- spi_tx_rx(0);
- while (len--)
- //*((uint8_t *)buf++) = spi_tx_rx(0);
- *(foo++) = spi_tx_rx(0);
- SPI_FLASH_CS_H();
- return 0;
- }
- ssize_t spi_flash_read(int addr, void *buf, size_t len, uint32_t timeout) {
- uint8_t* foo = (uint8_t *)buf;
- ssize_t ret = 0;
- // ret = tn_mutex_lock(&spi_mutex, timeout);
- // if (ret != TERR_NO_ERR)
- // return ret;
- SPI_FLASH_CS_L();
- spi_tx_rx(CMD_READ);
- send_addr(addr);
- while (len--)
- //*((uint8_t *)buf++) = spi_tx_rx(0);
- *(foo++) = spi_tx_rx(0);
- SPI_FLASH_CS_H();
- // tn_mutex_unlock(&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* foo = (uint8_t *)buf;
- // ret = tn_mutex_lock(&spi_mutex, timeout);
- // if (ret != TERR_NO_ERR)
- // return ret;
- // don't allow page wrapping
- ssize_t ret = 0;
- if ((addr & 0xFF) + len > 0xFF)
- len = 0x100 - (addr & 0xFF);
- ret = len;
- 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(*((uint8_t *)buf++));
- spi_tx_rx(*(foo++));
- SPI_FLASH_CS_H();
- wait_write_end();
- // tn_mutex_unlock(&spi_mutex);
- return ret;
- }
- ssize_t spi_flash_write(int addr, const void *buf, size_t len, uint32_t timeout) {
- uint8_t* foo = (uint8_t *)buf;
- int ret = 0, offset = 0;
- do {
- //ret = spi_flash_pp(addr + offset, buf + offset, len - offset, 0);
- ret = spi_flash_pp(addr + offset, foo + offset, len - offset, 0);
- offset += ret;
- } while (len - offset);
- return 0;
- }
- int spi_flash_chip_erase(uint32_t timeout) {
- 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();
- return 0;
- }
- int spi_flash_erase_sector(int addr, uint32_t timeout) {
- int ret = 0;
- // ret = tn_mutex_lock(&spi_mutex, timeout);
- // if (ret != TERR_NO_ERR)
- // return ret;
- 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();
- // tn_mutex_unlock(&spi_mutex);
- return 0;
- }
- /*
- bool spi_flash_init(void) {
- uint32_t i, ptable, bitsize = 0;
- uint8_t tmp[4];
- spi_flash_desc.present = false;
- spi_init_();
- // check SFDP magic
- 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;
- }*/
- 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;
- }
- 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";
- uint8_t txbuf2[] = "STM32F4xx SPI Firmware Library Example: communication with an M25P SPI FLASH\r\n";
- #define countof(a) (sizeof(a) / sizeof(*(a)))
- #define bufsize1 (countof(txbuf1)-1)
- #define bufsize2 (countof(txbuf2)-1)
- uint8_t rxbuf1[bufsize1] = {0};
- uint8_t rxbuf2[bufsize2] = {0};
- bool spi_flash_test(void) {
- uint16_t i;
- if (!spi_flash_init())
- return false;
- int ret = 0, addr = 0, offset = 0;
- for(i = 0; i < 1; i ++){//spi_flash_desc.sector_count
- //spi_flash_read(i*spi_flash_desc.sector_size, rxbuf1, bufsize1, 0);
- spi_flash_erase_sector(i*spi_flash_desc.sector_size,0);
- //spi_flash_read(0, rxbuf1, bufsize1, 0);
- spi_flash_write(i*spi_flash_desc.sector_size, txbuf1, bufsize1, 0);
- memset(rxbuf1, 0, bufsize1);
- spi_flash_read(i*spi_flash_desc.sector_size, rxbuf1, bufsize1, 0);
- if (memcmp(txbuf1, rxbuf1, bufsize1) != 0)
- return false;
- }
- return true;
- /*spi_flash_erase_sector(0,0);
- spi_flash_read(0, rxbuf1, bufsize1, 0);
- spi_flash_write(0, txbuf2, bufsize2, 0);
- memset(rxbuf2, 0, bufsize2);
- spi_flash_read(0, rxbuf2, bufsize2, 0);*/
- /*
- * TODO restore spi_flash_init();
- spi_flash_init();
- if (!spi_flash_desc.present)
- return -1;
- printf("\tPresent: %d sectors, %d bytes per sector (%d bytes total)\n",
- spi_flash_desc.sector_count,
- spi_flash_desc.sector_size,
- spi_flash_desc.sector_size * spi_flash_desc.sector_count);
- return 0;
- */
-
- }
|