Hi Neil,
The only intent I had for that example that does use MQX is because it worked on both Freedom and Tower to allow comparison and validation that example works on both too.
For either of the project, all the MQX projects need to be open and built prior to compiling the application.
The easiest method to get all required projects open to compile KSDK_1.3 application is to open the respective *.wsd file from the "Import-->Project of Projects--> Existing Projects Sets" options and click on the *.wsd file.
Ex: C:\Freescale\KSDK_1.3.0\middleware\filesystem\mfs\examples\sdcard\build\kds\sdcard_frdmk64f\sdcard_frdmk64f.wsd
This will open 6 projects!
Regards,
David
Hi David,
I had started the same project about a month ago and tried to move to KSDK_2.0_K64F, but I was getting errors during
compiling. I had to switch back to the KSDK_1.3.0 just to get the project moving, but I wanted to try going back to the
KSDK_2.0_K64F/w KDS_3.1.0.
Maybe switching to this and trying to slow down the clock could work, if the problem exist within a version issue?
Can you help me get over the compiling issues?
Thanks.
Hi David,
Update on KSDK_2.0_K64F, there is a driver example located C:\Freescale\SDK_2.0_K64F\boards\frdmk64f\driver_examples\sdcard_fatfs
Looking at the sdcard_fatfs.c file, I find the following:
#if defined BOARD_SDHC_CD_LOGIC_RISING
while (!(GPIO_ReadPinInput(BOARD_SDHC_CD_GPIO_BASE, BOARD_SDHC_CD_GPIO_PIN)))
{
}
where is the function GPIO_ReadPinInput declared?
I looked inside the following:
#include "fsl_uart.h"
#include "fsl_gpio.h"
#include "fsl_debug_console.h"
#include "ff.h"
#include "diskio.h"
#include "board.h"
#include "fsl_mpu.h"
#include "pin_mux.h"
#include "clock_config.h"
could not find it....
thanks,
Neil
Hi Neil,
Sorry for delay. I was visiting customer yesterday.
The example I was running on the FRDM-K64F will not run on the TWR-K64F. Too many differences.
But if you want an example that does run on both platforms then:
C:\Freescale\KSDK_1.3.0\middleware\filesystem\mfs\examples\sdcard\build\kds\sdcard_twrk64f120m
C:\Freescale\KSDK_1.3.0\middleware\filesystem\mfs\examples\sdcard\build\kds\sdcard_frdmk64f
Note the SDHC clock setting is based on the SD Card you use. And even similar cards that get configured with same clocking setting can differ in performance. I have two such SD Cards where one is 2GB and the other 8GB. They get setup for 25MHz but the closes configurable clock rate calculates out to 20MHz (I can measure that using o-scope). The 2GB SD Card will let me write 1234567 bytes in 2 seconds and the 8GB card takes 7 seconds! Just an observation.
Regards,
David
Thank you David,
I still haven't figured out the slowing clock issue. A colleague and I started wondering if its because our bus clock
configuration and how it is down on the FRDM-K64F evaluation board. This is just a suspicion, since we really can't
understand if everything else is the same, then it should work the same in our custome board.
I did noticed that the example you listed above is a KSDK_1.3.0, that is different from the KSDK_v2, I will try it out
and see what my results are?
Neil
Quick update,
After looking at the example in the KSDK_1.3.0, I noticed it uses MQX and when I try to compile, I get an
error saying that I am missing the psptypes.h file directory. I am not using MQX and don't want to be going
that path, since even if I can get the MQX stuff to work, it is not being supported by Freescale or NXP now.
Neil
Hi Neil,
Are you using KSDK_1.2?
If yes I went into it and only modified SDCARD_DRV_InitSd() as follows to change the clocking to 400kHz:
/*FUNCTION****************************************************************
*
* Function Name: SDCARD_DRV_InitSd
* Description: initialize SD memory card
*
*END*********************************************************************/
static sdhc_status_t SDCARD_DRV_InitSd(sdhc_card_t *card)
{
assert(card);
sdhc_status_t err = kStatus_SDHC_NoError;
card->cardType = kCardTypeSd;
if (kStatus_SDHC_NoError != SDCARD_DRV_AllSendCid(card))
{
return kStatus_SDHC_AllSendCidFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SendRca(card))
{
return kStatus_SDHC_SendRcaFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SendCsd(card))
{
return kStatus_SDHC_SendCsdFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SelectCard(card, true))
{
return kStatus_SDHC_SelectCardFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SendScr(card))
{
return kStatus_SDHC_SendScrFailed;
}
if (kStatus_SDHC_NoError !=
SDHC_DRV_ConfigClock(card->hostInstance, SDMMC_CLK_400KHZ)) //DES was SDMMC_CLK_25MHZ
{
return kStatus_SDHC_SetClockFailed;
}
if (DOES_HOST_SUPPORT_4BITS(card->host) && DOES_CARD_SUPPORT_4BITS(card))
{
if (kStatus_SDHC_NoError != SDCARD_DRV_SetBusWidth(card, kSdBusWidth4Bit))
{
return kStatus_SDHC_SetCardWideBusFailed;
}
if (kStatus_SDHC_NoError !=
SDHC_DRV_SetBusWidth(card->hostInstance, kSdhcBusWidth4Bit))
{
return kStatus_SDHC_SetBusWidthFailed;
}
}
if (DOES_HOST_SUPPORT_HIGHSPEED(card->host))
{
err = SDCARD_DRV_SwitchHighspeed(card);
if ((err != kStatus_SDHC_NoError) && (kStatus_SDHC_CardNotSupport != err))
{
return kStatus_SDHC_SwitchHighSpeedFailed;
}
else if (err == kStatus_SDHC_NoError)
{
if (kStatus_SDHC_NoError !=
SDHC_DRV_ConfigClock(card->hostInstance, SDMMC_CLK_400KHZ)) //DES was SDMMC_CLK_50MHZ
{
return kStatus_SDHC_SetClockFailed;
}
}
else
{
err = kStatus_SDHC_NoError;
}
}
if (SDCARD_DRV_SetBlockSize(card, FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE))
{
err = kStatus_SDHC_SetCardBlockSizeFailed;
}
return err;
}
This project (C:\Freescale\KSDK_1.2.0\examples\twrk64f120m\driver_examples\sdhc_sdcard\kds) sets the clocking up to 120MHz core, 60MHz peripheral and bus, and 24MHz flash.
Regards,
David
Hi David,
I am actually using the KSDK 1.3.0, but after looking at the function SDCARD_DRV_InitSd
it is the same on both KSDK 1.2.0 and KSDK 1.3.0. I have changed the same lines you
recommended, but unfortunately the clock doesn't seem to change from the 24MHz? It
feels like 24MHz is fixed somewhere in the code or a combination of register settings, signals
for 24MHz clock... weird!!!
Is there anything else you can think about that could cause this?
Some background info, I used George Gonzales, sample on setting up the FATfs + SDcard guide,
I believe he made back on 2014 or 2015? I don't know if this helps any, but I thought the more info
you had the better.
Thank you for keeping track with this issue.
Neil
Hi Neil,
Weird. I can change the clock, run the example, and measure with o-scope on pin 5 of the SD Card interface clock signal to see it change. Where are you measuring?
If you step over those clock API's do you see the clocking change on pin 5? Wondering if it does change it properly but then later the other code modifies it back to 24MHz??? Drawing straws so to speak.
Regards,
David
Hi David,
I am measuring on PIN 5, my pinout is VDD-4, DAT0-7, DAT1-8, DAT2-1, CD/DAT3-2, CMD-3
CLK-5, SD_SW-9, VSS-6 , the rest are tied to ground.
If I step over the clock API, I can see that the code is responsive. The reason I know its responsive
is because before the card can be configured with a clock setting, it must be first stopped, then once
the setting has been applied, then the clock is started once again. If I probe PIN5 while I am stepping
over these lines, I can see the clock stop, then start again.
I didn't try following the code afterwards and watching if when it is configured, it actually switches, I just
let the compiler run (trusting everything was set correctly) and watch to find the very disappointing 24MHz
is still there! LOL.........
I will try to follow it closely and let you know what I find.
thanks,
Neil
Hi David,
Stepping through the code, I found the following and I would like to confirm it with you to see if you the same.
The code leads me to the following function, which I believe is where the clock actually gets configured.
/*FUNCTION****************************************************************
*
* Function Name: SDHC_HAL_ConfigSdClock
* Description: configure clock of host controller, it will set the most
* close clock frequency to the given clock
*
*END*********************************************************************/
void SDHC_HAL_ConfigSdClock(SDHC_Type * base, sdhc_hal_sdclk_config_t* clkConfItms)
{
uint32_t divisor, freq, sysCtlReg;
assert(base);
assert(clkConfItms);
divisor = SDHC_HAL_INITIAL_DVS;
freq = SDHC_HAL_INITIAL_CLKFS;
/* Enables the IPG clock and no automatic clock gating off.
Enables the system clock and no automatic clock gating off.
Enables the peripheral clock and no automatic clock gating off.
Enables the SD clock. It should be disabled before changing the SD clock */
SDHC_CLR_SYSCTL(base, (SDHC_SYSCTL_IPGEN_MASK | SDHC_SYSCTL_HCKEN_MASK | \
SDHC_SYSCTL_PEREN_MASK | SDHC_SYSCTL_SDCLKEN_MASK));
/* If user want to disable the clock , directly return. */
if(!(clkConfItms->enable))
{
return;
}
if (clkConfItms->destClk > 0)
{
while((clkConfItms->maxHostClk / freq / SDHC_HAL_MAX_DVS > clkConfItms->destClk) &&
(freq < SDHC_HAL_MAX_CLKFS))
{
SDHC_HAL_NEXT_CLKFS(freq);
}
while((clkConfItms->maxHostClk / freq / divisor > clkConfItms->destClk) &&
(divisor < SDHC_HAL_MAX_DVS))
{
SDHC_HAL_NEXT_DVS(divisor);
}
clkConfItms->destClk = clkConfItms->maxHostClk / freq / divisor; <--------------- Here I see the change happening **********
clkConfItms->destClk = 400KHz coming in, after this line clkConfItms->destClk = 0, then the code continues (I didn't bother copying the rest
it should be the same for you) and finally it gets to this line:
while(!SDHC_BRD_PRSSTAT_SDSTB(base)) {}
/* nables the SD clock. It should be disabled before changing the SD clock frequency. */
SDHC_SET_SYSCTL(base, SDHC_SYSCTL_SDCLKEN_MASK);
If I am holding my probe on the clock (PIN5) I can see that after it passes the while statement, it enables the clock and once again
the 24MHz appears!
In my previous post, I had a concern with this line:
freq = SDHC_HAL_INITIAL_CLKFS; where SDHC_HAL_INITIAL_CLKFS = 2U as seen on fsl_sdhc_hal.h
from the manual, choosing 2U = Base clock divided by 4.
SDCLK Frequency Select
Used to select the frequency of the SDCLK pin. The frequency is not programmed directly. Rather this
register holds the prescaler (this register) and divisor (next register) of the base clock frequency register.
Setting 00h bypasses the frequency prescaler of the SD Clock. Multiple bits must not be set, or the
behavior of this prescaler is undefined. The two default divider values can be calculated by the frequency
of SDHC clock and the following divisor bits.
Table continues on the next page...
Memory map and register definition
K64 Sub-Family Reference Manual, Rev. 2, January 2014
1640 Freescale Semiconductor, Inc.
SDHC_SYSCTL field descriptions (continued)
Field Description
The frequency of SDCLK is set by the following formula: Clock frequency = (Base clock) / (prescaler x
divisor)
For example, if the base clock frequency is 96 MHz, and the target frequency is 25 MHz, then choosing
the prescaler value of 01h and divisor value of 1h will yield 24 MHz, which is the nearest frequency less
than or equal to the target. Similarly, to approach a clock value of 400 kHz, the prescaler value of 08h and
divisor value of eh yields the exact clock value of 400 kHz. The reset value of this field is 80h, so if the
input base clock ( SDHC clock ) is about 96 MHz, the default SD clock after reset is 375 kHz.
According to the SD Physical Specification Version 1.1 and the SDIO Card Specification Version 1.2, the
maximum SD clock frequency is 50 MHz and shall never exceed this limit.
Only the following settings are allowed:
01h Base clock divided by 2.
02h Base clock divided by 4.
04h Base clock divided by 8.
08h Base clock divided by 16.
10h Base clock divided by 32.
20h Base clock divided by 64.
40h Base clock divided by 128.
80h Base clock divided by 256.
I am not sure, if I am heading in the right direction, but I don't understand, if I am changing the same lines as you are,
that I would get a different result? Of course, this is just a suspicion of what could be happening, maybe it can at least
give you a clue as to why I am not seeing the same thing.
Please let me know your thoughts on this.
Neil Porven
Update,
David, on the side, I have two FRDM-K64F evaluation boards and a colleague has a TWR system, but he doesn't remember
if he has the K64 top board. Anyway, I have two questions:
1. Can I run the TWR example project on the FRDM evaluation board?
2. Is there a similar example project on the FRDM evaluation board, as in the TWR evaluation board?
I want to compare apples to apples and make sure is not my custom board the one with the issue.
Thanks,
Neil
Update,
Hi David, so I was able to use the FRDM-K64F evaluation board and using the example project, change the clock
to SDMMC_CLOCK_400KHZ and probe it. I was able to see the clock change properly.
At least now, I know I am changing the correct section in code and can see it working, at least on the evaluation board.
Now, I need to figure out what is different from one board to the other, or in software?
KDS_3.1+KSDK_v2 for FRDM-K64F
C:\NXP\KSDK_v2\SDK_2.0_FRDM-K64F_KDS\boards\frdmk64f\driver_examples\sdcard_fatfs\kds
I have two questions regarding this example:
1. I don't see a main under source, where is the main?
2. What is this project doing? I don't see anything in the console, I don't see any LEDs blinking??
Thank you
Update,
On my question 2, I found a Readme.txt file that explains how to work with the project and how to setup
a terminal device. I did this and it is working.
I am still looking for the link between what is happening between our board/software and the FRDM-K64F board.
Neil
Hi Neil,
Ok...I loaded the KSDK_1.3 C:\Freescale\KSDK_1.3.0\examples\twrk64f120m\driver_examples\sdhc_sdcard\kds example.
In file fsl_sdhc_card.c the following function I only made two edits to set the SD Card frequency to 400KHz and verified it using o-scope.
static sdhc_status_t SDCARD_DRV_InitSd(sdhc_card_t *card)
{
assert(card);
sdhc_status_t err = kStatus_SDHC_NoError;
card->cardType = kCardTypeSd;
if (kStatus_SDHC_NoError != SDCARD_DRV_AllSendCid(card))
{
return kStatus_SDHC_AllSendCidFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SendRca(card))
{
return kStatus_SDHC_SendRcaFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SendCsd(card))
{
return kStatus_SDHC_SendCsdFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SelectCard(card, true))
{
return kStatus_SDHC_SelectCardFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SendScr(card))
{
return kStatus_SDHC_SendScrFailed;
}
if (kStatus_SDHC_NoError !=
SDHC_DRV_ConfigClock(card->hostInstance, SDMMC_CLK_400KHZ)) //DES was SDMMC_CLK_25MHZ))
{
return kStatus_SDHC_SetClockFailed;
}
if (DOES_HOST_SUPPORT_4BITS(card->host) && DOES_CARD_SUPPORT_4BITS(card))
{
if (kStatus_SDHC_NoError != SDCARD_DRV_SetBusWidth(card, kSdBusWidth4Bit))
{
return kStatus_SDHC_SetCardWideBusFailed;
}
if (kStatus_SDHC_NoError !=
SDHC_DRV_SetBusWidth(card->hostInstance, kSdhcBusWidth4Bit))
{
return kStatus_SDHC_SetBusWidthFailed;
}
}
if (DOES_HOST_SUPPORT_HIGHSPEED(card->host))
{
err = SDCARD_DRV_SwitchHighspeed(card);
if ((err != kStatus_SDHC_NoError) && (kStatus_SDHC_CardNotSupport != err))
{
return kStatus_SDHC_SwitchHighSpeedFailed;
}
else if (err == kStatus_SDHC_NoError)
{
if (kStatus_SDHC_NoError !=
SDHC_DRV_ConfigClock(card->hostInstance, SDMMC_CLK_400KHZ)) //DES was SDMMC_CLK_50MHZ))
{
return kStatus_SDHC_SetClockFailed;
}
}
else
{
err = kStatus_SDHC_NoError;
}
}
if (SDCARD_DRV_SetBlockSize(card, FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE))
{
err = kStatus_SDHC_SetCardBlockSizeFailed;
}
return err;
}
Terminal Output attached for running default example and example at 400KHz.
Regards,
David
Hi David,
I can see there are two location on my fsl_sdhc_card.c
where I can change the clock, here is one:
/*FUNCTION****************************************************************
*
* Function Name: SDCARD_DRV_Init
* Description: initialize card on the given host controller
*
*END*********************************************************************/
sdhc_status_t SDCARD_DRV_Init(sdhc_host_t *host, sdhc_card_t *card)
{
sdhc_status_t err = kStatus_SDHC_NoError;
uint32_t acmd41Arg;
assert(card);
assert(host);
card->cardType = kCardTypeUnknown;
card->host = host;
card->hostInstance = host->instance;
if (SDHC_DRV_ConfigClock(card->hostInstance, SDMMC_CLK_400KHZ))
{
return kStatus_SDHC_SetClockFailed;
}
err = SDCARD_DRV_GoIdle(card);
if (err)
{
return kStatus_SDHC_SetCardToIdle;
}
acmd41Arg = card->host->ocrSupported;
err = SDCARD_DRV_SendIfCond(card);
if (err == kStatus_SDHC_NoError)
{
/* SDHC or SDXC card */
acmd41Arg |= SD_OCR_HCS;
card->caps |= SDMMC_CARD_CAPS_SDHC;
}
else
{
/* SDSC card */
err = SDCARD_DRV_GoIdle(card);
if (err)
{
return kStatus_SDHC_SetCardToIdle;
}
}
err = SDCARD_DRV_AppSendOpCond(card, acmd41Arg);
if (kStatus_SDHC_TimeoutError == err)
{
/* MMC card */
return kStatus_SDHC_NotSupportYet;
}
else if (err)
{
return kStatus_SDHC_SendAppOpCondFailed;
}
return SDCARD_DRV_InitSd(card);
}
also, I this one:
/*FUNCTION****************************************************************
*
* Function Name: SDCARD_DRV_InitSd
* Description: initialize SD memory card
*
*END*********************************************************************/
static sdhc_status_t SDCARD_DRV_InitSd(sdhc_card_t *card)
{
assert(card);
sdhc_status_t err = kStatus_SDHC_NoError;
card->cardType = kCardTypeSd;
if (kStatus_SDHC_NoError != SDCARD_DRV_AllSendCid(card))
{
return kStatus_SDHC_AllSendCidFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SendRca(card))
{
return kStatus_SDHC_SendRcaFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SendCsd(card))
{
return kStatus_SDHC_SendCsdFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SelectCard(card, true))
{
return kStatus_SDHC_SelectCardFailed;
}
if (kStatus_SDHC_NoError != SDCARD_DRV_SendScr(card))
{
return kStatus_SDHC_SendScrFailed;
}
if (kStatus_SDHC_NoError !=
SDHC_DRV_ConfigClock(card->hostInstance, SDMMC_CLK_400KHZ))
{
return kStatus_SDHC_SetClockFailed;
}
if (DOES_HOST_SUPPORT_4BITS(card->host) && DOES_CARD_SUPPORT_4BITS(card))
{
if (kStatus_SDHC_NoError != SDCARD_DRV_SetBusWidth(card, kSdBusWidth4Bit))
{
return kStatus_SDHC_SetCardWideBusFailed;
}
if (kStatus_SDHC_NoError !=
SDHC_DRV_SetBusWidth(card->hostInstance, kSdhcBusWidth4Bit))
{
return kStatus_SDHC_SetBusWidthFailed;
}
}
if (DOES_HOST_SUPPORT_HIGHSPEED(card->host))
{
err = SDCARD_DRV_SwitchHighspeed(card);
if ((err != kStatus_SDHC_NoError) && (kStatus_SDHC_CardNotSupport != err))
{
return kStatus_SDHC_SwitchHighSpeedFailed;
}
else if (err == kStatus_SDHC_NoError)
{
if (kStatus_SDHC_NoError !=
SDHC_DRV_ConfigClock(card->hostInstance, SDMMC_CLK_400KHZ))
{
return kStatus_SDHC_SetClockFailed;
}
}
else
{
err = kStatus_SDHC_NoError;
}
}
if (SDCARD_DRV_SetBlockSize(card, FSL_SDHC_CARD_DEFAULT_BLOCK_SIZE))
{
err = kStatus_SDHC_SetCardBlockSizeFailed;
}
return err;
}
As you can see, I changed both. Is it needed for the first one as well?
Do you have a similar function for the twrk64?
Thank you,
Neil
Hi David,
Its seems that 24MHz is all I can get. By the way, I am using my own board and my internal bus clock is 48MHz.
Thanks,
Neil
Quick update,
I think the twrk64 example is running an internal BUS clock of 4MHz and its being derived from the external oscillator.
I also noticed that the example does have SDCARD_DRV_Init and the internal clock is set to 400KHZ.
Do you believe the DIV needs to be set in my case running a 48MHZ clock?
thanks,
Neil
Another update,
I noticed that fsl_sdhc_hal.c has the following function:
void SDHC_HAL_ConfigSdClock(SDHC_Type * base, sdhc_hal_sdclk_config_t* clkConfItms)
It contains these two lines:
divisor = SDHC_HAL_INITIAL_DVS;
freq = SDHC_HAL_INITIAL_CLKFS;
SDHC_HAL_INITIAL_DVS is pre-defined to 1U
SDHC_HAL_INITIAL_CLKFS is pre-defined to 2U
trying to change these values inside the KDS, does absolutely nothing! I am trying to set them so:
SDHC_HAL_INITIAL_DVS is 0U (divide by 1)
SDHC_HAL_INITIAL_CLKFS is 40U (divide by 128)
with my internal bus running at 48MHz it should roughly give me 375KHz.
Neil
Hi Neil,
I'm testing with KDS_3.1+KSDK_v2 for FRDM-K64F and running the example C:\NXP\KSDK_v2\SDK_2.0_FRDM-K64F_KDS\boards\frdmk64f\driver_examples\sdcard_fatfs\kds .
In the fls_sd.c file SD_Init() function is around line 1011. This routine identifies the SD Card being used to determine what maximum clock rate to use. My test card is 2GB and can operate at high speed clocking (50MHz setting but 30MHz implemented).
The default 400KHz SD Card clocking is used to identify card and then the clock is increased and tested to see if it can go higher (my summary of the code).
Stepping through that code I found my card would get to line 1123 and try to set clock to 50MHz.
else if (error == kStatus_Success)
{
card->busClock_Hz = SDHC_SetSdClock(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_50MHZ);
}
When I measured with Oscope it was 30MHz.
Now when I replace that code with following:
else if (error == kStatus_Success)
{
card->busClock_Hz = SDHC_SetSdClock(card->host.base, card->host.sourceClock_Hz, SDMMC_CLOCK_400KHZ); //DES was SD_CLOCK_50MHZ);
}
Now when I measure I get 375kHZ and the example worked fine (just slower).
For your case you should be able to step through the code to see what clock rate it is determining your card can handle and then adjust down as you see fit.
Regards,
David