[En-Nut-Discussion] Improvement for faster mounting of large SD cards

Malte Marwedel m.marwedel at onlinehome.de
Tue Mar 2 12:52:42 CET 2010


Rob van Lieshout (PragmaLab) schrieb:
> Mixing up the code like you did by saving calls doesn't sound like a good
> idea to me and I would not encourage you to put the code in NutOS. The
> FS-module in the current NutOS benefits from functional separated parts
> within that module.

> I did not found the time yet to optimize the counting of the free clusters
> but it sure is on my list.
I later realized, that my improvement only speed up the mounting 
process, but not the time needed for the first write. A lot CPU time is 
used by the

static void PhatTableLoc(PHATVOL * vol, uint32_t clust, int tabnum, 
uint32_t * sect, uint32_t * pos)
  {
      uint32_t tabpos = clust * 4;

      *sect = vol->vol_tab_sect[tabnum] + tabpos / vol->vol_sectsz;
      *pos = tabpos % vol->vol_sectsz;
}
because for every PhatTableLoc() calculation, the function __udivmodsi4 
is called twice (each call needs 604 CPU clocks). This alone consumes 
1/3 of the CPU time for finding free clusters on an AVR.

By assuming that vol_sectsz is always something 2^n this could be made a 
lot faster. (Anyone using a memory where this is not the case?)

static void PhatTableLocNew(PHATVOL * vol, uint32_t clust, int tabnum, 
uint32_t * sect, uint32_t * pos)
{
     uint32_t tabpos = clust * 4;
     uint16_t sectsz = vol->vol_sectsz;
     *sect = tabpos;
     while(sectsz > 1) {
         *sect >>= 1;
         sectsz >>= 1;
     }
     *sect += vol->vol_tab_sect[tabnum];
     *pos = tabpos & ((vol->vol_sectsz)-1);
}

This does not make mounting as fast as my first suggestion, but does not 
mix up the functional separation and improves the time for the first 
write too.

To show that my code works, I ran a test program

int main(void) {
	PHATVOL vol;
	vol.vol_tab_sect[0] = 42;
	uint32_t clust, sectsz;
	for (sectsz = 1; sectsz < 16000; sectsz *= 2) {
		vol.vol_sectsz = sectsz;
		printf("\rtesting %i sector size\r", sectsz);
		fflush(stdout);
		for (clust = 0; clust < 10000000; clust++) {
			uint32_t poso, posn, secto, sectn;
			PhatTableLoc(&vol, clust, 0, &secto, &poso);
			PhatTableLocNew(&vol, clust, 0, &sectn, &posn);
			if ((secto != sectn) || (poso != posn)) {
				printf("Fail: sect: should %u is %u, pos: should %u is %u\n", secto, 
sectn, poso, posn);
				return 1;
			}
		}
	}
	puts("Test success                       ");
	return 0;
}

on my computer.

Malte



More information about the En-Nut-Discussion mailing list