-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Dynamically allocate the SD sector cache on use, save ~512 bytes when SD not used #4204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
35dd992
5cd00db
bfc025b
1d9af16
6c12968
22d8e3a
faa2552
8dcbf46
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -431,14 +431,16 @@ union cache_t { | |
class SdVolume { | ||
public: | ||
/** Create an instance of SdVolume */ | ||
SdVolume(void) :allocSearchStart_(2), fatType_(0) {} | ||
SdVolume(void) :allocSearchStart_(2), fatType_(0) { if (!cacheBuffer_) cacheBuffer_ = (cache_t *)malloc(sizeof(cache_t)); } | ||
/** Delete an instance of SdVolume */ | ||
~SdVolume() { free(cacheBuffer_); cacheBuffer_ = NULL; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The original cache was a static array, accessible from any instance. This change makes it a static pointer, and the constructor checks if it has been allocated before, in which case nothing is done, or not, in which case it is allocated. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had only considered the single global SD object. Since then, with the BSSL stuff I've been introduced to the wonders of the std::shared_ptr and this would be a good use of one like you suggest. Will see if I can fix it up this weekend. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, but using a separate refcnt instead of std::ptr as there needs to be a special-case for cnt==1 (like the BearSSL issue). |
||
/** Clear the cache and returns a pointer to the cache. Used by the WaveRP | ||
* recorder to do raw write to the SD card. Not for normal apps. | ||
*/ | ||
static uint8_t* cacheClear(void) { | ||
cacheFlush(); | ||
cacheBlockNumber_ = 0XFFFFFFFF; | ||
return cacheBuffer_.data; | ||
return cacheBuffer_->data; | ||
} | ||
/** | ||
* Initialize a FAT volume. Try partition one first then try super | ||
|
@@ -499,7 +501,7 @@ class SdVolume { | |
// value for action argument in cacheRawBlock to indicate cache dirty | ||
static uint8_t const CACHE_FOR_WRITE = 1; | ||
|
||
static cache_t cacheBuffer_; // 512 byte cache for device blocks | ||
static cache_t *cacheBuffer_; // 512 byte cache for device blocks | ||
static uint32_t cacheBlockNumber_; // Logical number of block in the cache | ||
static Sd2Card* sdCard_; // Sd2Card object for cache | ||
static uint8_t cacheDirty_; // cacheFlush() will write block if true | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,7 +86,7 @@ recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.fla | |
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/arduino.ar" "{object_file}" | ||
|
||
## Combine gc-sections, archives, and objects | ||
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{build.path}/arduino.ar" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" | ||
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -Wl,-M -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{build.path}/arduino.ar" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #4186 :) |
||
|
||
## Create eeprom | ||
recipe.objcopy.eep.pattern= | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null is not checked. I don't really know myself what to do in constructors when this happen.
Maybe you can also help with this in #4134 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe errors in constructors can only throw an exception. Unfortunately, that's not the Arduino way, so I'm as at a loss as yourself.
The alternative here, and elsewhere, is to use lazy allocation and/or defensive. Before use of the cache it can be checked and the method can error out if it can't be allocated, assuming the API allows it. Perusing the SD headers, it looks like SEGV'ing is really the only thing that's possible using the current API.
Something like link time optimization (-flto) might eliminate the need for this kind of change as it should be able to detect no call graph into this static class variable, but I've not been able to make it work (and I believe we're upgrading GCC soon, and at that point it should be "automatic" anyway).