UPDATE: Latest Src: http://controllingtheinter.net/2018/03/05/esp8266-nonos-sdk-sprintf-stright-from-flash/

So, One of my ESP projects requires a Large HTML file being massaged and sent out with Data to display to the client. What I currently do now is use SpiRead and read it into a Malloc that is the size of the HTML. Then after I use OS_SprintF on the string and add the coordinating information into the HTML. That works great, However minor issue. After the HTML grows in development the HTML gets into the size of around 6-8k, Allocating 16k of Memory just to send out an HTML file can become a challenge for the ESP due to the lack of heap memory. This is just a prototype but I’m developing on the idea of reading the Spi 4 bytes at a time and calling SprintF accordingly whenever I see %s. %d. %c etc etc. I am not done at the moment but I am working on idea’s on simple ways to accomplish this.

#include <stdarg.h> //Required for VAList
void flashsprintf(char *s, uint32_t address, int n, …)
{

int ret;
int val;
va_list ap;
va_start(ap, n);

int numberOfVars = 0;
int i, ii = 0;
char * ss = s; //Backup Ptr
for (numberOfVars=0; s[i]; s[i]==’%’ ? numberOfVars++ : *s++);
s = ss; //RestorePtr

os_printf(“start\r\n”);
for (i=0; i<=(os_strlen(s)-1); i++)
{
//os_printf(“%d-%c\r\n”, i, s[i]);
if (s[i] == ‘%’)
{
switch(s[i+1])
{
case ‘s’  :
val=va_arg(ap,char *);
break; /* optional */

case ‘d’  :
os_printf(“Dec “);
val=va_arg(ap,int);
break; /* optional */

/* you can have any number of case statements */
default : /* Optional */
os_printf(“Unknown “);
}
}
}

os_printf(“%d”, i);

for (ii=0;ii<i;ii++)
{
val=va_arg(ap,int);
os_printf (” %d”,val);
}
//ret = vsprintf(s, fmt, ap);
va_end(ap);
return ret;
}

 

 

As additional step I tried to rewrite this code using Visual Studio the Mike’s operating system kind had to expand my knowledge on how SprintF reports are neat the hood. One things I found kind of interesting is that when you pass an argument to a C function that does have a set amount of parameters SprintF uses an internal function called VA_list that is used to parse through each corner and then clean up the stack afterwards allowing the function to return back to the callee properly. I would assume I would have to do is do an SPI read and mimic the same type of logic to accomplish what I’m looking for. In the end I believe I can redo some heap memory usage by approximately 40% which is a huge deal when you only have 32K of heap to work with. I’m not done with this code yet. This is more brainstorming pseudocode for me. I’ll come back and update this code when i come up with more of a polished solution.

 

#include “stdafx.h”
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h> //Required for VAList
#define _CRT_SECURE_NO_WARNINGS
int flashsprintf(char *buffer, char *s, int n, …)
{
int ret;
void * val;
void * args[4];
va_list ap;
va_start(ap, n);
int numberOfVars = 0;
int i, ii, index = 0;
char * ss = s; //Backup Ptr
for (numberOfVars = 0; s[numberOfVars]; s[numberOfVars] == ‘%’ ? numberOfVars++ : *s++);
s = ss; //RestorePtr
printf(“start\r\n“);
for (i = 0; i <= (strlen(s) – 1); i++)
{
//os_printf(“%d-%c\r\n“, i, s[i]);
if (s[i] == ‘%’)
{
switch (s[i + 1])
{
case ‘s’:
args[index] = va_arg(ap, char *);
index++;
break; /* optional */
case ‘d’:
//int *p1 = (int *)malloc(sizeof(int));
//p1 = &va_arg(ap, int);
//args[index] = p1;
args[index] = (void *)va_arg(ap, int);
index++;
break; /* optional */
   /* you can have any number of case statements */
//default: /* Optional */
//printf(“Unknown “);
}
}
}
switch (index – 1)
{
case 0:
sprintf(buffer, s, args[0]);
case 1:
sprintf(buffer, s, args[0], args[1]);
case 2:
sprintf(buffer, s, args[0], args[1], args[2]);
default:
printf(“default”);
}
printf(“%d”, i);
/*
for (ii = 0; ii<i; ii++)
{
val = va_arg(ap, int);
printf(” %d”, val);
}
*/
//ret = vsprintf(s, fmt, ap);
va_end(ap);
return 0;
}
int main()
{
char buffer[512];
flashsprintf(buffer, “%s%d%s”, 3, “test”, 5, “tester”);
    return 0;
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax