uSDFS icon indicating copy to clipboard operation
uSDFS copied to clipboard

m_sdhc_baudrate caculation wrong

Open manitou48 opened this issue 8 years ago • 2 comments

line 467 in sdhc.c (cosmetic?) is in error me thinks. it reads m_sdhc_baudrate=F_CPU/((1<<minpresc)*(mindiv+1));

but minpresc is not a shift value, it should be minpresc << 1 BUT, that is not quite right either, because if minpresc is 0, you want the multiplier to be 1, so maybe int tmp = minpresc << 1; if (tmp == 0) tmp = 1; m_sdhc_baudrate=F_CPU/(tmp*(mindiv+1));

manitou48 avatar Jan 17 '17 13:01 manitou48

I believe that the following code should be correct

// get dividers from requested baud rate 
	uint32_t aux=F_CPU;
	uint32_t ii=0,jj=1;
	uint32_t baudrate=kbaudrate*1000;

	while(aux/(16*(1<<ii))>baudrate) ii++;
	while(aux/(jj*(1<<ii))>baudrate) jj++;

	uint32_t minpresc=ii;
	uint32_t mindiv=jj-1;

	m_sdhc_baudrate=F_CPU/((1<<minpresc) * (mindiv+1));

	// Change dividers
	sysctl = SDHC_SYSCTL & 
			(~ (SDHC_SYSCTL_DTOCV_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DVS_MASK));
	SDHC_SYSCTL = sysctl | 
			(SDHC_SYSCTL_DTOCV(0x0E) | SDHC_SYSCTL_SDCLKFS(minpresc) | SDHC_SYSCTL_DVS(mindiv));

presc is a single bit and div is a number

This includes the (untested case) that presc = 0 is valid input and that presc=0 does not prevent div to be effective. The way I calculate is if F_CPU=96 Mhz and baudrate is 3 kHz then ii=1 and jj=16 presc=1 and div = 15 and therefore 96MHz/((1<<presc)*(div+1)) = 3kHz

Can you agree?

WMXZ-EU avatar Jan 17 '17 20:01 WMXZ-EU

You chose a convenient example where ii is 1. the minpresc in the register should have values of 0, 1,2,4,8,16 32 ... your current example, i don't think will set the register value correctly

what will you get with CPU 96mhz and target baudrate 400K, 96000000/(16*15) = 400000 register: prescale value 8, divisor value 14 On Tue, Jan 17, 2017 at 12:09:21PM -0800, WMXZ-EU wrote:

I believe that the following code should be correct

// get dividers from requested baud rate 
	uint32_t aux=F_CPU;
	uint32_t ii=0,jj=1;
	uint32_t baudrate=kbaudrate*1000;

	while(aux/(16*(1<<ii))>baudrate) ii++;
	while(aux/(jj*(1<<ii))>baudrate) jj++;

	uint32_t minpresc=ii;
	uint32_t mindiv=jj-1;

	m_sdhc_baudrate=F_CPU/((1<<minpresc) * (mindiv+1));

	// Change dividers
	sysctl = SDHC_SYSCTL & 
			(~ (SDHC_SYSCTL_DTOCV_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DVS_MASK));
	SDHC_SYSCTL = sysctl | 
			(SDHC_SYSCTL_DTOCV(0x0E) | SDHC_SYSCTL_SDCLKFS(minpresc) | SDHC_SYSCTL_DVS(mindiv));

presc is a single bit and div is a number

This includes the (untested case) that presc = 0 is valid input and that presc=0 does not prevent div to be effective. The way I calculate is if F_CPU=96 Mhz and baudrate is 3 kHz then ii=1 and jj=16 presc=1 and div = 15 and therefore 96MHz/((1<<presc)*(div+1)) = 3kHz

Can you agree?

-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/WMXZ-EU/uSDFS/issues/5#issuecomment-273284489

-- Tom Dunigan [email protected] http://tnlandforms.us

manitou48 avatar Jan 17 '17 22:01 manitou48