Ver código fonte

Тесты новых модулей. Добави модуль кнопок. Добавил документы.

TelenkovDmitry 1 ano atrás
pai
commit
8b1a0c32b9

BIN
doc/Описание схемы 048260х MAIO124.docx


+ 424 - 424
fw/modules/spi_flash/spi_flash.c

@@ -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

+ 25 - 16
fw/user/main.c

@@ -17,7 +17,7 @@ int main(void)
     nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
 	__enable_irq();
   
-    //extend_SRAM();
+    extend_SRAM();
   
     system_clock_config();
 
@@ -36,7 +36,7 @@ int main(void)
     //printf("\n\n\n\nModule universal IO [FW %s] loading....\r\n\n", VERSION);
         
     //
-    //usb_init();
+    usb_init();
     
 #if 1
     taskENTER_CRITICAL();      
@@ -53,6 +53,8 @@ int main(void)
     
     xTaskCreate(misc_task, "misc_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
     
+    xTaskCreate(button_task, "button_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
+    
     taskEXIT_CRITICAL();
     
     vTaskStartScheduler();
@@ -91,18 +93,24 @@ void init_task(void *argument)
     save_mode_init();
     // TODO Для теста отключаем безопасный режим работы
     save_mode_set(false);   
-/*    
+  
     io_port_init();
-    in_exint_init();
-*/    
+    
+    //in_exint_init();    
 
     gpio_wdt_init();
     gpio_mbaddr_init();
+    
+// -------------------------------------------------------------------------- //
+// Кнопки  
+    
+    button_init();
+    
 // -------------------------------------------------------------------------- //
 // Uptime    
     
     uptime_init();
-    //out_as_pwm();
+
 // -------------------------------------------------------------------------- //
 // RTC    
     
@@ -132,28 +140,29 @@ void init_task(void *argument)
 // -------------------------------------------------------------------------- //    
 // Тесты
     //pwm_test(); // тесы PWM
+    gpio_get_rev();
     
 // -------------------------------------------------------------------------- //    
 // RNDIS
     
-    //usb_eth_init();
+    usb_eth_init();
         
     // Тесты таймеров
     //mux_led_test_init();
     
+#if 0    
     // Тесты SPI flash
-    //common_spi_init();
-    //InitFS(PRIM_DRIVE);
-    //spi_flash_test();
-      
+    common_spi_init();
+    InitFS(PRIM_DRIVE);
+    spi_flash_test();
+#endif     
+    
     // Тесты USB
     //usb_eth_init();
-    
-    
+     
       
     //vTaskDelete(NULL);
-    
-    
+            
     for (;;)
     {
         mux_led_proc();
@@ -171,7 +180,7 @@ void test_hw_task(void *argument)
     {
         vTaskDelay(100);
         
-        //mux_led_blink();
+        mux_led_blink();
     }
 }
 

+ 39 - 38
fw/user/main.h

@@ -1,39 +1,40 @@
-#ifndef __MAIN_H
-#define __MAIN_H
-
-#include "at32f403a_407.h"
-#include "at32f403a_407_board.h"
-#include "at32f403a_407_clock.h"
-#include "common_config.h"
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-#include "usb_eth.h"
-#include "mux.h"
-#include "misc.h"
-#include "spi_common.h"
-#include "user_fatfs.h"
-#include "spi_flash.h"
-#include "usb_eth.h"
-#include "extended_sram.h"
-#include "modbus.h"
-#include "common_gpio.h"
-#include "io.h"
-#include "input.h"
-#include "output.h"
-#include "sys_api.h"
-#include "settings_api.h"
-#include "update.h"
-#include "uptime.h"
-#include "rtc.h"
-#include "mb.h"
-#include "io_utils.h"
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
-
-
-
-
+#ifndef __MAIN_H
+#define __MAIN_H
+
+#include "at32f403a_407.h"
+#include "at32f403a_407_board.h"
+#include "at32f403a_407_clock.h"
+#include "common_config.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+#include "usb_eth.h"
+#include "mux.h"
+#include "misc.h"
+#include "spi_common.h"
+#include "user_fatfs.h"
+#include "spi_flash.h"
+#include "usb_eth.h"
+#include "extended_sram.h"
+#include "modbus.h"
+#include "common_gpio.h"
+#include "io.h"
+#include "input.h"
+#include "output.h"
+#include "sys_api.h"
+#include "settings_api.h"
+#include "update.h"
+#include "uptime.h"
+#include "rtc.h"
+#include "mb.h"
+#include "io_utils.h"
+#include "buttons.h"
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+
+
+
+
 #endif

BIN
output/fw.bin


Diferenças do arquivo suprimidas por serem muito extensas
+ 130 - 125
project/ewarm/module_universal_io.dep


+ 3 - 0
project/ewarm/module_universal_io.ewp

@@ -2691,6 +2691,9 @@
         </group>
         <group>
             <name>peripherals</name>
+            <file>
+                <name>$PROJ_DIR$\..\..\shared\peripherals\src\buttons.c</name>
+            </file>
             <file>
                 <name>$PROJ_DIR$\..\..\shared\peripherals\src\common_gpio.c</name>
             </file>

+ 3 - 0
project/ewarm/module_universal_io.ewt

@@ -2910,6 +2910,9 @@
         </group>
         <group>
             <name>peripherals</name>
+            <file>
+                <name>$PROJ_DIR$\..\..\shared\peripherals\src\buttons.c</name>
+            </file>
             <file>
                 <name>$PROJ_DIR$\..\..\shared\peripherals\src\common_gpio.c</name>
             </file>

+ 82 - 0
shared/peripherals/inc/buttons.h

@@ -0,0 +1,82 @@
+#ifndef __BUTTONS_H
+#define __BUTTONS_H
+
+#include "at32f403a_407.h"
+#include <stdbool.h>
+
+
+// Кнопки
+typedef enum 
+{  
+  BUT_RESET = 0,
+  BUT_SET,
+
+} BUTTON_t;
+
+
+// Статус кнопки
+typedef enum 
+{  
+  BUT_ON = 0,
+  BUT_OFF,
+  BUT_NO_DEFINE,
+  
+} BUTTON_STATE_t;
+
+
+// Структура параметров объекта Button
+typedef struct 
+{  
+  gpio_type         *port;          // Порт
+  uint32_t 			pin;            // Пин
+  uint16_t          timeDelay;      // Время задержки антидребезга (время измеряется
+                                    // во временных интервалах с которыми вызывается
+                                    // обработчик кнопки
+  uint16_t          counterDelay;   // Счетчик антидребезга
+  BUTTON_STATE_t    stateOld;       // Прошлое состояние кнопки
+  BUTTON_STATE_t    stateNew;       // Текущее состояние кнопки
+  void              (*pressHandler)();   // Обработчик нажатия кнопки
+  void              (*unpressHandler)(uint8_t btn); // Обработчик отпускания кнопки
+  uint8_t           ID;             // уникальный идентификатор (можно не использовать)
+  uint32_t          counterActivation;
+  uint16_t          timeActivation_1;
+  uint16_t          timeActivation_2;
+  bool              fActivation;
+} BUTTON_NO_FIX_t; 
+
+
+//
+void button_init(void);
+   
+/**
+  * @brief   Возвращает сотояние ключа
+  * @retval  1 - линия разомкнута
+  *          0 - линия замкнута
+  */
+BUTTON_STATE_t BUTTON_GetState(BUTTON_NO_FIX_t *button);
+
+bool BUTTON_GetStateInt(BUTTON_t button);
+
+/**
+  * @brief  Обработчик кнопки без фиксации. В обработчике реализована защита
+  *         от дребезга с помощью задержки. Защита срабатывает при нажатии 
+  *         и при отпускании.
+  * @param *button: указатель на структуру типа BUTTON_NO_FIX
+  * @retval нет
+  */
+void BUTTON_NoFixHandler(BUTTON_NO_FIX_t *button);
+
+// Опрос кнопок
+void button_task(void *params);
+
+// Заглушки
+void void_handler(void);
+void void_handler_btn(uint8_t btn);
+
+//
+void reset_handler(void);
+
+//
+void set_handler(uint8_t btn);
+
+#endif /* #ifndef __BUTTONS_H */

+ 194 - 0
shared/peripherals/src/buttons.c

@@ -0,0 +1,194 @@
+#include "buttons.h"
+#include "settings_api.h"
+#include "common_config.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include <string.h>
+#include <stdio.h>
+
+
+BUTTON_NO_FIX_t reset_but;
+BUTTON_NO_FIX_t set_but;
+
+
+//  
+void button_init(void) 
+{
+    gpio_init_type gpio_initstructure;
+    
+    // key reset
+    gpio_initstructure.gpio_pull           = GPIO_PULL_NONE;  
+    gpio_initstructure.gpio_mode           = GPIO_MODE_INPUT;  
+    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+    gpio_initstructure.gpio_pins           = GPIO_PINS_8;
+    gpio_init(GPIOB, &gpio_initstructure);
+    
+    // key set
+    gpio_initstructure.gpio_pins           = GPIO_PINS_5;
+    gpio_init(GPIOD, &gpio_initstructure);
+  
+    reset_but.port              = GPIOB;
+    reset_but.pin			    = GPIO_PINS_8;
+    reset_but.timeDelay         = 1;
+    reset_but.pressHandler      = reset_handler;
+    reset_but.unpressHandler    = void_handler_btn;
+    reset_but.counterActivation = 0;
+    reset_but.timeActivation_1  = 300; // 30 секунд
+    reset_but.timeActivation_2  = 600; 
+    reset_but.fActivation       = false;
+    
+    set_but.port                = GPIOD;
+    set_but.pin			        = GPIO_PINS_5;
+    set_but.timeDelay           = 1;
+    set_but.pressHandler        = void_handler;
+    set_but.unpressHandler      = set_handler;
+    set_but.counterActivation   = 0;
+    set_but.timeActivation_1    = 300;   // обычное нажатие
+    set_but.timeActivation_2    = 600; // 15 секунд
+    set_but.fActivation         = false;
+    
+    reset_but.stateOld = BUTTON_GetState(&reset_but);
+    set_but.stateOld  = BUTTON_GetState(&set_but);
+}
+
+// Возвращает сотояние ключа
+BUTTON_STATE_t BUTTON_GetState(BUTTON_NO_FIX_t *button)
+{
+    return (BUTTON_STATE_t)gpio_input_data_bit_read(button->port, button->pin);
+}
+
+//
+bool button_get_state_int(BUTTON_t button)
+{
+    switch (button)
+    {
+        case BUT_RESET :
+            return !(bool)gpio_input_data_bit_read(reset_but.port, reset_but.pin);
+        break;
+    
+        case BUT_SET :
+            return !(bool)gpio_input_data_bit_read(set_but.port, set_but.pin);
+        break;
+    
+        default : break;
+    }
+    return false;
+}
+
+/**
+  * @brief  Обработчик кнопки без фиксации. В обработчике реализована защита
+  *         от дребезга с помощью задержки. Защита срабатывает при нажатии 
+  *         и при отпускании.
+  * @param *button: указатель на структуру типа BUTTON_NO_FIX
+  * @retval нет
+  */
+void BUTTON_NoFixHandler(BUTTON_NO_FIX_t *button)
+{
+    uint8_t temp;
+  
+    if (button->stateNew != BUT_NO_DEFINE)
+    {  
+        temp = (uint8_t)gpio_input_data_bit_read(button->port, button->pin);
+      
+        if (temp == 1)  // определяем текущее (новое) состояние кнопки        
+            button->stateNew = BUT_ON;
+        else
+            button->stateNew = BUT_OFF;
+  
+        if (button->stateNew != button->stateOld)  // зафиксирован факт нажатия/отжатия
+            button->stateNew = BUT_NO_DEFINE;  // переводим кнопку в неопределенное состояние
+    }
+    else
+    {
+        button->counterDelay++;             // запускаем счетчик на задержку
+    
+        if (button->counterDelay > button->timeDelay)  // задержка закончилась
+        {
+            button->counterDelay = 0;
+            
+            temp = (uint8_t)gpio_input_data_bit_read(button->port, button->pin);
+   	  
+            button->counterActivation = 0;
+		
+            //if (temp == 0)  // определяем текущее (новое) состояние кнопки        
+            if (temp == 1)  // определяем текущее (новое) состояние кнопки        
+            {  
+                button->stateNew = BUT_ON;
+                button->unpressHandler(1);
+            }  
+            else
+            {  
+                button->stateNew = BUT_OFF;
+                button->pressHandler();
+            }
+        }
+    }
+  
+    button->stateOld = button->stateNew;
+}
+
+
+/**
+  * @brief  Обработчик кнопки без фиксации. Кнопка срабатывает через определеное
+            время нажатия.
+  * @param *button: указатель на структуру типа BUTTON_NO_FIX
+  * @retval нет
+  */
+void BUTTON_DellayHandler(BUTTON_NO_FIX_t *button)
+{
+    /* Кнопка нажата. Ведем отсчет времени удержания */
+    //if ((uint8_t)gpio_input_data_bit_read(button->port, button->pin) == 1)  // определяем текущее (новое) состояние кнопки
+    if ((uint8_t)gpio_input_data_bit_read(button->port, button->pin) == 0)  // определяем текущее (новое) состояние кнопки
+    {  
+        button->counterActivation++;
+        button->fActivation = false;
+	
+        /* Кнопка нажата более необходимого времени - начинаем чаще мигать диодом */
+        //if (button->counterActivation > button->timeActivation)
+        //  LED_SetStatusLedFreq(100);
+    }
+    /* Кнопку отжата. Если до этого она была нажата нужное время - вызываем хендлер */
+    else
+    {
+        if ((button->counterActivation > button->timeActivation_2) && button->fActivation == false)
+        {  
+            button->fActivation = true;
+            button->unpressHandler(2);
+        }
+        else if ((button->counterActivation > button->timeActivation_1) && button->fActivation == false)
+        {
+            button->fActivation = true;
+            button->unpressHandler(1);
+        }
+        else
+            button->counterActivation = 0;
+    }		
+}
+
+// Опрос кнопок
+void button_task(void *params) 
+{
+    for (;;) 
+    {
+        BUTTON_NoFixHandler(&reset_but);
+        BUTTON_NoFixHandler(&set_but);
+        vTaskDelay(100);  
+    }
+}
+
+// Заглушки
+void void_handler(void) {}
+void void_handler_btn(uint8_t btn) {}
+
+//
+void reset_handler(void)
+{
+    NVIC_SystemReset();
+}
+
+//
+void set_handler(uint8_t btn)
+{
+}
+
+

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff