Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 12 of 12

Thread: KinetisSDHC.c clock setting error

  1. #1

    KinetisSDHC.c clock setting error

    In KinetisSDHC.c there is a macro used to set the SDHC clock speed:
    Code:
    // prescale can be 2, 4, 8, 16, 32, 64, 128, 256
    // divisor can be 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
    #define SDHC_SYSCTL_DIVISOR(prescale, divisor) \
    (SDHC_SYSCTL_DVS((prescale)>>1)|SDHC_SYSCTL_SDCLKFS((divisor)-1))
    This invokes a couple of macros in kinetis.h:

    Code:
    #define SDHC_SYSCTL_SDCLKFS(n) (uint32_t)(((n) & 0xFF)<<8) // SDCLKFrequency Select
    #define SDHC_SYSCTL_SDCLKFS_MASK ((uint32_t)0x0000FF00)
    #define SDHC_SYSCTL_DVS(n) (uint32_t)(((n) & 0xF)<<4) // Divisor
    #define SDHC_SYSCTL_DVS_MASK ((uint32_t)0x000000F0)
    The problem is that the code is feeding the prescale value (a single bit set in an eight bit field) to the divisor macro (four bits) and the divisor value to the prescale macro. The result is clock frequencies are set to values that aren't predictable since operation with more than one bit set in the prescaler field is undefined.

    A simple change fixes it:
    Code:
    #define SDHC_SYSCTL_DIVISOR(prescale, divisor) \
    (SDHC_SYSCTL_SDCLKFS((prescale)>>1)|SDHC_SYSCTL_DVS((divisor)-1))

  2. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,771
    I agree this is an error. if i run T3.6 @180mhz, SDHC_SYSCTL is 0xE0318. 3 is illegal value for SDCLKFS. sector read time is 452 us. Manually setting to 0xE0138, then SDHC clock should be 180/2/4 (22.5 MHz) and sector read time is 427us.

    I'm not sure why Paul hasn't replied. I'll try filing an issue on github

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    27,990
    Sorry about the delay on this (and so many other things). My spare dev cycles are currently going into some final cleanup with the recent server move, and an ongoing project with our PCB vendor to make very minor changes on all the boards to improve manufacturability... and of course keeping up with answering questions.

  4. #4
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,771
    No rest for the weary. thanks

    Upon further review, I think you can improve SDHC clock values in some cases. So if F_CPU is 72mhz, one could get 24mhz SDHC clock SDCLKFS 0, and divisor 3. that is better than your 18 mhz.
    Last edited by manitou; 01-06-2017 at 05:47 PM.

  5. #5

  6. #6
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,771
    Quote Originally Posted by manitou View Post
    Upon further review, I think you can improve SDHC clock values in some cases. So if F_CPU is 72mhz, one could get 24mhz SDHC clock SDCLKFS 0, and divisor 3. that is better than your 18 mhz.
    Any chance you can tighten up some of the divisors in KinetisSDHC.c, i have a perl script that generates the following divisors
    Code:
    F_CPU 240000000
      400000  (375000)  div(64,10)
      25000000  (24000000)  div(1,10)
      50000000  (48000000)  div(1,5)
    F_CPU 216000000
      400000  (375000)  div(64,9)
      25000000  (24000000)  div(1,9)
      50000000  (43200000)  div(1,5)
    F_CPU 192000000
      400000  (400000)  div(32,15)
      25000000  (24000000)  div(1,8)
      50000000  (48000000)  div(1,4)
    F_CPU 180000000
      400000  (375000)  div(32,15)
      25000000  (22500000)  div(1,8)
      50000000  (45000000)  div(1,4)
    F_CPU 168000000
      400000  (375000)  div(32,14)
      25000000  (24000000)  div(1,7)
      50000000  (42000000)  div(1,4)
    F_CPU 144000000
      400000  (375000)  div(32,12)
      25000000  (24000000)  div(1,6)
      50000000  (48000000)  div(1,3)
    F_CPU 120000000
      400000  (375000)  div(32,10)
      25000000  (24000000)  div(1,5)
      50000000  (40000000)  div(1,3)
    F_CPU 96000000
      400000  (400000)  div(16,15)
      25000000  (24000000)  div(1,4)
      50000000  (48000000)  div(1,2)
    F_CPU 72000000
      400000  (375000)  div(16,12)
      25000000  (24000000)  div(1,3)
      50000000  (36000000)  div(1,2)
    F_CPU 48000000
      400000  (400000)  div(8,15)
      25000000  (24000000)  div(1,2)
      50000000  (48000000)  div(1,1)
    F_CPU 24000000
      400000  (400000)  div(4,15)
      25000000  (24000000)  div(1,1)
      50000000  (24000000)  div(1,1)
    I guess I could modify the perl script to generate your macros ....

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    27,990
    Do these actually work and produce the desired frequencies?

    The datasheet says the clock prescale must be at least 2.

  8. #8
    The data sheet states "Setting 00h bypasses the frequency prescaler of the SD Clock."

  9. #9
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,771
    Quote Originally Posted by PaulStoffregen View Post
    Do these actually work and produce the desired frequencies?

    The datasheet says the clock prescale must be at least 2.
    I confirmed a few of the configurations provided "faster" megabits/sec, but i don't have a way to actually measure the SD clock. As noted above, 0 bypasses the prescaler (e.g., prescaler =1)

  10. #10
    Senior Member
    Join Date
    Jul 2014
    Posts
    3,497
    Quote Originally Posted by manitou View Post
    As noted above, 0 bypasses the prescaler (e.g., prescaler =1)
    This is what I was reading too and coding also without problems.
    (it is only a line or so above, but on previous page)
    As soon as I have access to a SDIO sniffer board (next week), I will test clock rate.
    Last edited by WMXZ; 01-17-2017 at 06:08 AM.

  11. #11
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,771
    I believe SdFat lib also calculates SD clock using prescale of 0 as needed.

  12. #12
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    27,990
    I've put this on my list for 1.36. It will happen. Sorry, I need to cut off changes and release 1.35 now.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •