Skip to content

Commit 3670639

Browse files
author
kolban
committed
Mon Dec 12 16:51:18 CST 2016
1 parent 2322f80 commit 3670639

File tree

7 files changed

+381
-0
lines changed

7 files changed

+381
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
COMPONENT_ADD_INCLUDEDIRS=.
+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
This is a simple read-only implementation of a file system. It uses a block of data coming from the
3+
mkespfsimg tool, and can use that block to do abstracted operations on the files that are in there.
4+
It's written for use with httpd, but doesn't need to be used as such.
5+
*/
6+
7+
/*
8+
* ----------------------------------------------------------------------------
9+
* "THE BEER-WARE LICENSE" (Revision 42):
10+
* Jeroen Domburg <[email protected]> wrote this file. As long as you retain
11+
* this notice you can do whatever you want with this stuff. If we meet some day,
12+
* and you think this stuff is worth it, you can buy me a beer in return.
13+
* ----------------------------------------------------------------------------
14+
*/
15+
16+
17+
//These routines can also be tested by comping them in with the espfstest tool. This
18+
//simplifies debugging, but needs some slightly different headers. The #ifdef takes
19+
//care of that.
20+
21+
#include <stdio.h>
22+
#include <stdint.h>
23+
#include <stdlib.h>
24+
#include <string.h>
25+
26+
#include <esp_spi_flash.h>
27+
#include <esp_log.h>
28+
#include <esp_err.h>
29+
30+
#include "espfsformat.h"
31+
#include "espfs.h"
32+
#include "sdkconfig.h"
33+
34+
static char tag[] = "espfs";
35+
36+
37+
struct EspFsFile {
38+
EspFsHeader *header;
39+
char decompressor;
40+
int32_t posDecomp;
41+
char *posStart;
42+
char *posComp;
43+
void *decompData;
44+
};
45+
46+
static spi_flash_mmap_handle_t handle;
47+
static void *espFlashPtr = NULL;
48+
49+
EspFsInitResult espFsInit(void *flashAddress, size_t size) {
50+
51+
spi_flash_init();
52+
esp_err_t rc = spi_flash_mmap((uint32_t) flashAddress, 64*1024*2, SPI_FLASH_MMAP_DATA, (const void **)&espFlashPtr, &handle);
53+
if (rc != ESP_OK) {
54+
ESP_LOGD(tag, "rc from spi_flash_mmap: %d", rc);
55+
}
56+
57+
// check if there is valid header at address
58+
EspFsHeader *testHeader = (EspFsHeader *)espFlashPtr;
59+
60+
if (testHeader->magic != ESPFS_MAGIC) {
61+
ESP_LOGE(tag, "No valid header at flash address. Expected to find %x and found %x", ESPFS_MAGIC, testHeader->magic);
62+
return ESPFS_INIT_RESULT_NO_IMAGE;
63+
}
64+
65+
return ESPFS_INIT_RESULT_OK;
66+
}
67+
68+
69+
70+
// Returns flags of opened file.
71+
int espFsFlags(EspFsFile *fh) {
72+
if (fh == NULL) {
73+
ESP_LOGD(tag, "File handle not ready");
74+
return -1;
75+
}
76+
77+
int8_t flags;
78+
memcpy((char*)&flags, (char*)&fh->header->flags, 1);
79+
return (int)flags;
80+
}
81+
82+
//Open a file and return a pointer to the file desc struct.
83+
EspFsFile *espFsOpen(char *fileName) {
84+
if (espFlashPtr == NULL) {
85+
ESP_LOGD(tag, "Call espFsInit first!");
86+
return NULL;
87+
}
88+
char *flashAddress = espFlashPtr;
89+
char *hpos;
90+
char *namebuf;
91+
EspFsHeader *header;
92+
EspFsFile *fileData;
93+
//Strip initial slashes
94+
while(fileName[0] == '/') {
95+
fileName++;
96+
}
97+
//Go find that file!
98+
while(1) {
99+
hpos=flashAddress;
100+
//Grab the next file header.
101+
header = (EspFsHeader *)flashAddress;
102+
103+
if (header->magic != ESPFS_MAGIC) {
104+
ESP_LOGD(tag, "Magic mismatch. EspFS image broken.");
105+
return NULL;
106+
}
107+
if (header->flags & FLAG_LASTFILE) {
108+
ESP_LOGD(tag, "End of image. File not found.");
109+
return NULL;
110+
}
111+
//Grab the name of the file.
112+
flashAddress += sizeof(EspFsHeader);
113+
namebuf = (char *)flashAddress;
114+
if (strcmp(namebuf, fileName) == 0) {
115+
//Yay, this is the file we need!
116+
flashAddress += header->nameLen; //Skip to content.
117+
fileData = (EspFsFile *)malloc(sizeof(EspFsFile)); //Alloc file desc mem
118+
if (fileData==NULL) {
119+
return NULL;
120+
}
121+
fileData->header = (EspFsHeader *)hpos;
122+
fileData->decompressor = header->compression;
123+
fileData->posComp = flashAddress;
124+
fileData->posStart = flashAddress;
125+
fileData->posDecomp = 0;
126+
if (header->compression == COMPRESS_NONE) {
127+
fileData->decompData = NULL;
128+
} else {
129+
ESP_LOGD(tag, "Invalid compression: %d", header->compression);
130+
return NULL;
131+
}
132+
return fileData;
133+
}
134+
//We don't need this file. Skip name and file
135+
flashAddress += header->nameLen+header->fileLenComp;
136+
if ((int)flashAddress&3) {
137+
flashAddress += 4-((int)flashAddress & 3); //align to next 32bit val
138+
}
139+
}
140+
}
141+
142+
//Read len bytes from the given file into buff. Returns the actual amount of bytes read.
143+
int espFsRead(EspFsFile *fh, char *buff, int len) {
144+
int flen;
145+
if (fh==NULL) {
146+
return 0;
147+
}
148+
149+
memcpy((char*)&flen, (char*)&fh->header->fileLenComp, 4);
150+
151+
if (fh->decompressor == COMPRESS_NONE) {
152+
int toRead;
153+
toRead = flen-(fh->posComp-fh->posStart);
154+
if (len > toRead) {
155+
len = toRead;
156+
}
157+
ESP_LOGD(tag, "copying %d bytes from 0x%x to 0x%x", len, (uint32_t)fh->posComp, (uint32_t)buff);
158+
memcpy(buff, fh->posComp, len);
159+
fh->posDecomp += len;
160+
fh->posComp += len;
161+
return len;
162+
}
163+
return 0;
164+
}
165+
166+
int espFsAccess(EspFsFile *fh, void **buf, size_t *len) {
167+
*buf = fh->posStart;
168+
*len = fh->header->fileLenComp;
169+
return *len;
170+
}
171+
172+
//Close the file.
173+
void espFsClose(EspFsFile *fh) {
174+
if (fh == NULL) return;
175+
free(fh);
176+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef ESPFS_H
2+
#define ESPFS_H
3+
#include <stdlib.h>
4+
// This define is done in Makefile. If you do not use default Makefile, uncomment
5+
// to be able to use Heatshrink-compressed espfs images.
6+
//#define ESPFS_HEATSHRINK
7+
8+
typedef enum {
9+
ESPFS_INIT_RESULT_OK,
10+
ESPFS_INIT_RESULT_NO_IMAGE,
11+
ESPFS_INIT_RESULT_BAD_ALIGN
12+
} EspFsInitResult;
13+
14+
typedef struct EspFsFile EspFsFile;
15+
16+
EspFsInitResult espFsInit(void *flashAddress, size_t size);
17+
EspFsFile *espFsOpen(char *fileName);
18+
int espFsFlags(EspFsFile *fh);
19+
int espFsRead(EspFsFile *fh, char *buff, int len);
20+
void espFsClose(EspFsFile *fh);
21+
int espFsAccess(EspFsFile *fh, void **buf, size_t *len);
22+
23+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#ifndef ESPROFSFORMAT_H
2+
#define ESPROFSFORMAT_H
3+
4+
/*
5+
Stupid cpio-like tool to make read-only 'filesystems' that live on the flash SPI chip of the module.
6+
Can (will) use lzf compression (when I come around to it) to make shit quicker. Aligns names, files,
7+
headers on 4-byte boundaries so the SPI abstraction hardware in the ESP8266 doesn't crap on itself
8+
when trying to do a <4byte or unaligned read.
9+
*/
10+
11+
/*
12+
The idea 'borrows' from cpio: it's basically a concatenation of {header, filename, file} data.
13+
Header, filename and file data is 32-bit aligned. The last file is indicated by data-less header
14+
with the FLAG_LASTFILE flag set.
15+
*/
16+
17+
18+
#define FLAG_LASTFILE (1<<0)
19+
#define FLAG_GZIP (1<<1)
20+
#define COMPRESS_NONE 0
21+
#define COMPRESS_HEATSHRINK 1
22+
#define ESPFS_MAGIC 0x73665345
23+
24+
typedef struct {
25+
int32_t magic;
26+
int8_t flags;
27+
int8_t compression;
28+
int16_t nameLen;
29+
int32_t fileLenComp;
30+
int32_t fileLenDecomp;
31+
} __attribute__((packed)) EspFsHeader;
32+
33+
#endif

filesystems/espfs/main.c

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <freertos/FreeRTOS.h>
2+
#include <freertos/task.h>
3+
#include <esp_system.h>
4+
#include <esp_log.h>
5+
#include <espfs.h>
6+
#include "sdkconfig.h"
7+
8+
char tag[] = "espfs_main";
9+
static void * flashAddress = (void *)(4*1024*1024 - 10 *64*1024); // 0x36 0000
10+
11+
void doWork(void *ignore) {
12+
13+
char buff[5*1024];
14+
ESP_LOGD(tag, "Flash address is 0x%x", (int)flashAddress);
15+
if (espFsInit(flashAddress, 64*1024) != ESPFS_INIT_RESULT_OK) {
16+
ESP_LOGD(tag, "Failed to initialize espfs");
17+
return;
18+
}
19+
20+
EspFsFile *fh = espFsOpen("files/test3.txt");;
21+
22+
if (fh != NULL) {
23+
int sizeRead = 0;
24+
sizeRead = espFsRead(fh, buff, sizeof(buff));
25+
ESP_LOGD(tag, "Result: %.*s", sizeRead, buff);
26+
27+
size_t fileSize;
28+
char *data;
29+
sizeRead = espFsAccess(fh, (void **)&data, &fileSize);
30+
ESP_LOGD(tag, "Result from access: %.*s", fileSize, data);
31+
32+
espFsClose(fh);
33+
vTaskDelete(NULL);
34+
}
35+
}
36+
void app_main(void)
37+
{
38+
xTaskCreatePinnedToCore(&doWork, "doWork", 8000, NULL, 5, NULL, 0);
39+
40+
}
41+

memory/esp32_memory.h

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* esp32_memory.h
3+
*
4+
* Created on: Dec 9, 2016
5+
* Author: kolban
6+
*/
7+
8+
#ifndef MAIN_ESP32_MEMORY_H_
9+
#define MAIN_ESP32_MEMORY_H_
10+
11+
#include <esp_system.h>
12+
#include <esp_log.h>
13+
14+
static uint32_t _heapFreeBefore;
15+
static uint32_t _counter = 0;
16+
17+
#define HEAP_CHANGE_START() _heapFreeBefore = esp_get_free_heap_size()
18+
#define HEAP_CHANGE_END(_EYECATCHER) { \
19+
uint32_t newSize = esp_get_free_heap_size(); \
20+
uint32_t value = _heapFreeBefore - newSize; \
21+
if (value !=0) { \
22+
ESP_LOGD("memory", _EYECATCHER ": Heap changed by %d, new size: %d, counter: %d", value, newSize, _counter); \
23+
_counter = 0; \
24+
} else { _counter++; }\
25+
}
26+
27+
28+
#endif /* MAIN_ESP32_MEMORY_H_ */

sockets/server/socket_server.c

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include <lwip/sockets.h>
2+
#include <esp_log.h>
3+
#include <string.h>
4+
#include <errno.h>
5+
#include "sdkconfig.h"
6+
7+
#define PORT_NUMBER 8001
8+
9+
static char tag[] = "socket_server";
10+
11+
/**
12+
* Create a listening socket. We then wait for a client to connect.
13+
* Once a client has connected, we then read until there is no more data
14+
* and log the data read. We then close the client socket and start
15+
* waiting for a new connection.
16+
*/
17+
void socket_server(void *ignore) {
18+
struct sockaddr_in clientAddress;
19+
struct sockaddr_in serverAddress;
20+
21+
// Create a socket that we will listen upon.
22+
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
23+
if (sock < 0) {
24+
ESP_LOGE(tag, "socket: %d %s", sock, strerror(errno));
25+
goto END;
26+
}
27+
28+
// Bind our server socket to a port.
29+
serverAddress.sin_family = AF_INET;
30+
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
31+
serverAddress.sin_port = htons(PORT_NUMBER);
32+
int rc = bind(sock, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
33+
if (rc < 0) {
34+
ESP_LOGE(tag, "bind: %d %s", rc, strerror(errno));
35+
goto END;
36+
}
37+
38+
// Flag the socket as listening for new connections.
39+
rc = listen(sock, 5);
40+
if (rc < 0) {
41+
ESP_LOGE(tag, "listen: %d %s", rc, strerror(errno));
42+
goto END;
43+
}
44+
45+
while (1) {
46+
// Listen for a new client connection.
47+
socklen_t clientAddressLength = sizeof(clientAddress);
48+
int clientSock = accept(sock, (struct sockaddr *)&clientAddress, &clientAddressLength);
49+
if (clientSock < 0) {
50+
ESP_LOGE(tag, "accept: %d %s", clientSock, strerror(errno));
51+
goto END;
52+
}
53+
54+
// We now have a new client ...
55+
int total = 10*1024;
56+
int sizeUsed = 0;
57+
char *data = malloc(total);
58+
59+
// Loop reading data.
60+
while(1) {
61+
ssize_t sizeRead = recv(clientSock, data + sizeUsed, total-sizeUsed, 0);
62+
if (sizeRead < 0) {
63+
ESP_LOGE(tag, "recv: %d %s", sizeRead, strerror(errno));
64+
goto END;
65+
}
66+
if (sizeRead == 0) {
67+
break;
68+
}
69+
sizeUsed += sizeRead;
70+
}
71+
72+
// Finished reading data.
73+
ESP_LOGD(tag, "Data read (size: %d) was: %.*s", sizeUsed, sizeUsed, data);
74+
free(data);
75+
close(clientSock);
76+
}
77+
END:
78+
vTaskDelete(NULL);
79+
}

0 commit comments

Comments
 (0)