2014-07-09 09:51 AM
Hello,
I have a working SDIO FATFS project on an STM32F4 Discovery PCB.This project works nicely at system clock frequencies down to 24 MHz.When I try running the project at system clocks of 16 MHz and 8MHz, the SDIO Clock will not even turn on.I forced the PLL output on in the system_stm32f4xx.c file and the SDIO clock comes on.This results in either a hard fault handler or file IO errors from the f_write() and f_read() operations.We are trying to run our circuit at as low a speed as possible in order to save power and still have reliable SDIO functionality.Is there a minimum SYSCLK freq spec that I should be aware of?I am aware of the requirement for the 8/3 SDIO_CK/PCLK2 max frequency ratio.For the 8MHz SYSCLK design I am using the 8MHz HSE crystal, 8MHz SYSCLK, 12.8MHz SDIO CLK and 8MHz PCLK2.The summary information from my system_stm32f4xx.c file is below: *============================================================================= * Supported STM32F40xx/41xx/427x/437x devices *----------------------------------------------------------------------------- * System Clock source | HSE *----------------------------------------------------------------------------- * SYSCLK(Hz) | 8000000 *----------------------------------------------------------------------------- * HCLK(Hz) | 8000000 *----------------------------------------------------------------------------- * AHB Prescaler | 1 *----------------------------------------------------------------------------- * APB1 Prescaler | 1 *----------------------------------------------------------------------------- * APB2 Prescaler | 1 *----------------------------------------------------------------------------- * HSE Frequency(Hz) | 8000000 *----------------------------------------------------------------------------- * PLL_M | 8 *----------------------------------------------------------------------------- * PLL_N | 192 *----------------------------------------------------------------------------- * PLL_P | 8 *----------------------------------------------------------------------------- * PLL_Q | 15 *----------------------------------------------------------------------------- * PLLI2S_N | NA *----------------------------------------------------------------------------- * PLLI2S_R | NA *----------------------------------------------------------------------------- * I2S input clock | NA *----------------------------------------------------------------------------- * VDD(V) | 3.3 *----------------------------------------------------------------------------- * Main regulator output voltage | Scale2 mode *----------------------------------------------------------------------------- * Flash Latency(WS) | 0 *----------------------------------------------------------------------------- * Prefetch Buffer | ON *----------------------------------------------------------------------------- * Instruction cache | ON *----------------------------------------------------------------------------- * Data cache | ON *----------------------------------------------------------------------------- Thank You,Forrest2014-07-09 12:40 PM
Running from my HSE (16 MHz)
SYS:16000000 H:16000000, P1:4000000, P2:8000000 HSE Source PLL using HSE SDIOClock : 24000000 12000000 Write at 5.85 MBps, Read at 8.21 MBps SDIOClock : 16000000 8000000 Write at 3.18 MBps, Read at 3.71 MBps SDIOClock : 12800000 6400000 Write at 2.63 MBps, Read at 2.99 MBps Anyhow, seems serviceable. PLL must be running2014-07-10 08:39 AM
Hi Clive1,
Thanks for running your own test on this. I suspected it was entirely possible.I was actually able to get the 16MHZ and 8MHz SYSCLK versions of my SDIO project to work last night by changing the divisor value in stm32f4_discovery.hI changed the divisor from 1 to 2 and that gives me a 12MHz SDIO Clock.// FJD: 07/09/2014 Attempting to reduce SDIO transfer clock speed to get around DMA lockup// when running at low Sysclock speeds (8MHz)://#define SDIO_TRANSFER_CLK_DIV ((uint8_t)0x1) // Original Setting#define SDIO_TRANSFER_CLK_DIV ((uint8_t)0x2)My only concern is forcing the PLL ON since the normal startup code does not enable it at SYSCLK freqs of 8 and 16MHz. It comes on without my intervention in system_stm32f4xx.cif the clock is 24MHz or greater. Otherwise, I force it on by setting bit 24 to a 1 as shown below:/* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF; // FJD: turning on the PLLON bit (bit 24): RCC->CR |= (uint32_t)0x01000000; // 0000 0001 0000 0000 0000 0000 0000 0000So, I have a working project at 8MHz SYSCLK. My concern now is whether or not my approach is reliable or is it going to cause an issue later.Could you offer any advice?Thank You,Forrest2014-07-10 09:12 AM
I used SDIO_TRANSFER_CLK_DIV of zero, ie 0=DIV2, 1=DIV3, 2=DIV4
192 / 8 = 24 MHz SDIOCLK PERIPHERAL 24 / 4 = 6 MHz SDIO BUS CLOCK Yes you would need to customize the code in system_stm32f4xx.c to reflect your design, and desired configuration. It's a project specific file, and expected to be tailored to suit. You'd want to enable the PLL, and wait for it to lock, after you started the HSE and waited for it to start. I have code that starts the 16 MHz HSE, but will fall back to the HSI if that doesn't start, it then configures and starts the PLL from the applicable clock. I'm not sure I'd describing it as 'forcing the PLL ON', you just turn it ON, as it would be done normally, but then at the end select HSE to run the processor, and not the PLL....
#if 1 // Run From HSE/HSI
if (Status == 1) // HSE Running
{
/* Select the main HSE as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_HSE;
/* Wait till the main HSE is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_HSE);
}
else
{
/* Select the main HSI as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_HSI;
/* Wait till the main HSI is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_HSI);
}
#else
/* Select the main PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL); /* Wait till the main PLL is used as system clock source */
#endif
...
2014-07-18 01:17 PM
Hi Clive1,
Thanks for your insights.The code you listed looks very similar to my clock initialization code.Thanks,Forrest2015-11-08 08:23 AM
Hi Clive,
I've followed this full post and tested direct HSI (16 MHz) as system clock (without PLL) and HSI as PLL input for 48MHz SDIOCLK. SDIO_CK needs to be < 16MHz (SDIO_INIT_CLK_DIV > 2). To reduce power consumption, if I set MSI as sytem clock (4.194 MHz, range_6), SDIO also works with PLL(HSI). Now SDIO_CK needs to be < 3MHz ( 2.823 MHz or 2.66 MHz with SDIO_INIT_CLK_DIV = 0xE or 0xF).Is it a good idea to employ two internal clocks MSI and HSI simultaneously in a state. What problem might occur in long run? My configuration:** in system_stm32l1xx.c file****static void SetSysClockHSI(void){ __IO uint32_t StartUpCounter = 0, HSIStatus = 0; RCC->CR |= ((uint32_t)RCC_CR_HSION); /* Wait till HSI is ready and if Time out is reached exit */ do { HSIStatus = RCC->CR & RCC_CR_HSIRDY; StartUpCounter++; } while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT)); if ((RCC->CR & RCC_CR_HSIRDY) != RESET) { HSIStatus = (uint32_t)0x01; } else { HSIStatus = (uint32_t)0x00; } if (HSIStatus == (uint32_t)0x01) { /* Enable 64-bit access */ FLASH->ACR |= FLASH_ACR_ACC64; /* Enable Prefetch Buffer */ FLASH->ACR |= FLASH_ACR_PRFTEN; /* Flash 1 wait state */ FLASH->ACR |= FLASH_ACR_LATENCY; /* Enable the PWR APB1 Clock */ RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* Select the Voltage Range 1 (1.8V) */ PWR->CR = PWR_CR_VOS_0; /* Wait Until the Voltage Regulator is ready */ while((PWR->CSR & PWR_CSR_VOSF) != RESET) { } /* HCLK = SYSCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; /* PCLK1 = HCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; /* PLL configuration */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL | RCC_CFGR_PLLDIV)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLDIV3); /* Enable PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0) { } /* Select HSI as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSI; /* Wait till HSI is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04) { } } else { }}** At the starting of main file****int main(void){ /* Set MSI clock range to 4.194 MHz */ RCC_MSIRangeConfig(RCC_MSIRange_6); /* Select MSI as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_MSI); /* Wait till MSI is used as system clock source */ while (RCC_GetSYSCLKSource() != 0x00) {} --------- ------ }2015-11-08 08:54 AM
The thread deals with the F4 parts, I really don't know how applicable any of it is to the L1 series ones. I'm not using L1 parts, and have no hardware to evaluate.
You'll have to review the clock trees and dependencies of the L1.I'm not sure what long term effects you expect, some designs don't expect clock inversions, ie expect APB2 >= APB1 always. These issues would exhibit in rather immediate data integrity issues. The latency in discovering these would be if you don't adequately validate the data to/from the media during development, which at some point would cause the data or file system structures to get corrupted in the field.