@jonne I have done some testing of the SD Card Loader hang that was earlier noticed with bigger size binaries. I added “const uint8_t background_bmp[] {…}” table to a simple C++ test app, and tested the background_bmp with different allocated sizes. I think it does not matter much what kind of test app is used. I used the sound test app.
If the resulted binary was 129 kb or lower, I did not experience any hang. With the 135 kb binary it was hanging. However, it was not so straightforward, as 138 kb binary did not hang (!).
I have attached it the"main.cpp" & “My_settings.h” which should result 135 kb binary. Replace the original files in the “Examples/HelloWorld” folder with new ones, and copy the resulted binary to the SD card. The hang should occur after the “success!!” text was displayed in the loader.
Your description of the problem and max size where problem arises gives me an idea what is the matter.
I put a safety catch (max sector number) in early stages of development to make sure high area of memory was not overwritten. I have a feeling it might still be effective
@Hanski : the problem turned out to be more difficult to track than I thought
The problem was that my function for calculating first page of each flash sector was faulty
/* Check is it the first page in the sector */
if (address == (sector-24)*0x4000 + 0x18000) firstpage = true;
So the mistake was that each sector below 0x18000 is 4 kB (0x1000). (as per User Manual for LPC11U68, page 438) and each sector above 0x18000 is 32kB and my algorithm was faulty.
Now, if you look at my formula, for sector 25 (address 0x20000) the formula gave 0x1C000 (not 0x20000) meaning the first page of the flash sector would have not been identified
Why this made a difference is that prior to writing each sector each sector must be erased correctly which was not happening. Firstpage was never true for address above 0x20000, the sectors above 24 were not erased and therefore binary was never written to flash.
The reason why I never noticed this that for the first 32kB sector (sector 24, address 0x18000) the formula does return the right address. So sector 24 did work, everything looked alright but all big binaries were truncated at 0x20000 !
By replacing the faulty calculation with a brute force check, the problem was solved.
Instead of a brute force, why don’t we just fix your calculation?
The problem is that 0x4000 isn’t 32KB, it’s 16KB. 32 * 1024 converted to hex is 0x8000.
Therefore your calculation can be fixed by making it:
/* Check is it the first page in the sector */
if (sector < 24) {
if (address == sector * 0x1000) firstpage = true;
} else {
if (address == (sector - 24) * 0x8000 + 0x18000) firstpage = true;
}
(Unrelated: I wonder if the Cortex M0+ has a fused multiply-add instruction?)
I took the liberty of creating a pull request for this method:
I haven’t checked with an actual SD card because I haven’t got round to getting a microSD for the Pokitto,
but I checked the maths involved and I’m almost certain that it calculates the offset properly.
I tested the calculations using a C# program:
using System;
namespace SectorTest
{
class Program
{
static void Main(string[] args)
{
for (uint i = 0; i <= 28; ++i)
{
Console.WriteLine("Test {0}", i);
uint bad = BadAddress(i);
uint good = GoodAddress(i);
Console.WriteLine("Bad Range: {0:X} - {1:X}", bad, bad + (0x8000 - 1));
Console.WriteLine("Good Range: {0:X} - {1:X}", good, good + (0x8000 - 1));
Console.WriteLine();
}
Console.ReadKey();
}
static uint BadAddress(uint sector)
{
if (sector < 24)
return sector * 0x1000;
else
return (sector - 24) * 0x4000 + 0x18000;
}
static uint GoodAddress(uint sector)
{
if (sector < 24)
return sector * 0x1000;
else
return (sector - 24) * 0x8000 + 0x18000;
}
}
}
The GoodAddress method matches up with the chart you provided.
(While peeking at the code I can see a few other possible improvements as well,
but I’m not sure how I’d go about testing them or if they’d be worthwhile.)
Now I’ve thought about it, I think the masking based approach would probably be both smaller and faster, so maybe I should withdraw my PR and either submit a new one or allow you to add the change?
I’ll leave it to you to decide.
It’s also possible to reduce it to just a one-liner:
Instead of withdrawing my PR I’ve just applied a new commit on top of the other one since both achieve the same thing and it’s probably less hassle than closing and making a new commit.
As I said before, what we do is up to you.
I don’t mind if you’d rather I closed the PR and you applied the change yourself since the masking approach was your idea.
(Also, sorry for making 3 replies a row, but I can never remember if people get notified of edits or not.)
@jonne You can create topics for each TODO task and community members could work on it. If work is so complicated cut them into little pieces for example not whole graphic DMA integration but just DMA integration for high resolution mode etc. Experienced community members could look PRs and decide to merge or not.