Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of DDRO_Farrari by
pll.cpp@1:6a820a0ca03b, 2013-10-21 (annotated)
- Committer:
- liangzhen
- Date:
- Mon Oct 21 22:36:51 2013 +0000
- Revision:
- 1:6a820a0ca03b
- Parent:
- 0:84a8bcfbdec9
- Child:
- 10:95e9932f7990
mbed code for Farrari board
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
liangzhen | 0:84a8bcfbdec9 | 1 | #include "pll.h" |
liangzhen | 0:84a8bcfbdec9 | 2 | |
liangzhen | 0:84a8bcfbdec9 | 3 | unsigned long long calc_pll_freqs(unsigned int prediv, unsigned int multint_upper, unsigned int multint, |
liangzhen | 0:84a8bcfbdec9 | 4 | unsigned int range_upper, unsigned int rangea, unsigned int rangeb){ |
liangzhen | 0:84a8bcfbdec9 | 5 | |
liangzhen | 0:84a8bcfbdec9 | 6 | if(prediv < 1 || prediv > 32){ |
liangzhen | 0:84a8bcfbdec9 | 7 | pc.printf("Prediv out of 1-32 range\r\n"); |
liangzhen | 0:84a8bcfbdec9 | 8 | } |
liangzhen | 0:84a8bcfbdec9 | 9 | if(multint_upper < 1 || multint_upper > 4){ |
liangzhen | 0:84a8bcfbdec9 | 10 | pc.printf("Multint_upper out of 1-4 range\r\n"); |
liangzhen | 0:84a8bcfbdec9 | 11 | } |
liangzhen | 0:84a8bcfbdec9 | 12 | if(multint < 1 || multint > 255){ |
liangzhen | 0:84a8bcfbdec9 | 13 | pc.printf("Multint out of 1-255 range\r\n"); |
liangzhen | 0:84a8bcfbdec9 | 14 | } |
liangzhen | 0:84a8bcfbdec9 | 15 | if(multint_upper * multint > 255){ |
liangzhen | 0:84a8bcfbdec9 | 16 | pc.printf("Multint_upper * Multint out of 1-255 range\r\n"); |
liangzhen | 0:84a8bcfbdec9 | 17 | } |
liangzhen | 0:84a8bcfbdec9 | 18 | if(!(range_upper == 1 || range_upper == 2 || range_upper == 4)){ |
liangzhen | 0:84a8bcfbdec9 | 19 | pc.printf("Range_upper out of 1,2,4 range\r\n"); |
liangzhen | 0:84a8bcfbdec9 | 20 | } |
liangzhen | 0:84a8bcfbdec9 | 21 | if(rangea < 1 || rangea > 32){ |
liangzhen | 0:84a8bcfbdec9 | 22 | pc.printf("RangeA out of 1-32 range\r\n"); |
liangzhen | 0:84a8bcfbdec9 | 23 | } |
liangzhen | 0:84a8bcfbdec9 | 24 | if(rangeb < 1 || rangeb > 32){ |
liangzhen | 0:84a8bcfbdec9 | 25 | pc.printf("RangeB out of 1-32 range\r\n"); |
liangzhen | 0:84a8bcfbdec9 | 26 | } |
liangzhen | 0:84a8bcfbdec9 | 27 | |
liangzhen | 1:6a820a0ca03b | 28 | int dco = (PLL_REF / prediv) * multint_upper * multint; |
liangzhen | 1:6a820a0ca03b | 29 | if(dco < 2500000 || dco > 5000000){ |
liangzhen | 1:6a820a0ca03b | 30 | pc.printf("Dco=%d out of 2.5G-5G range\r\n",dco); |
liangzhen | 0:84a8bcfbdec9 | 31 | } |
liangzhen | 1:6a820a0ca03b | 32 | int internal = dco / multint_upper; |
liangzhen | 1:6a820a0ca03b | 33 | if(internal < 9800 || internal > 3200000){ |
liangzhen | 1:6a820a0ca03b | 34 | pc.printf("internal=%d out of 9.8M-3.2G range\r\n",internal); |
liangzhen | 0:84a8bcfbdec9 | 35 | } |
liangzhen | 1:6a820a0ca03b | 36 | int prescale_dco = dco / range_upper; |
liangzhen | 1:6a820a0ca03b | 37 | if(prescale_dco > 3200000){ |
liangzhen | 1:6a820a0ca03b | 38 | pc.printf("Prescale DCO out of 0-3.2G range\r\n"); |
liangzhen | 0:84a8bcfbdec9 | 39 | } |
liangzhen | 1:6a820a0ca03b | 40 | int out_a = prescale_dco / rangea; |
liangzhen | 1:6a820a0ca03b | 41 | if(out_a < 20000 || out_a > 3000000){ |
liangzhen | 0:84a8bcfbdec9 | 42 | pc.printf("Out A out of 20M-3.0G range\r\n"); |
liangzhen | 0:84a8bcfbdec9 | 43 | } |
liangzhen | 1:6a820a0ca03b | 44 | int out_b = prescale_dco / rangeb; |
liangzhen | 1:6a820a0ca03b | 45 | if(out_b < 20000 || out_b > 3000000){ |
liangzhen | 0:84a8bcfbdec9 | 46 | pc.printf("Out B out of 20M-3.0G range\r\n"); |
liangzhen | 0:84a8bcfbdec9 | 47 | } |
liangzhen | 0:84a8bcfbdec9 | 48 | |
liangzhen | 0:84a8bcfbdec9 | 49 | return out_a; |
liangzhen | 0:84a8bcfbdec9 | 50 | } |
liangzhen | 0:84a8bcfbdec9 | 51 | |
liangzhen | 0:84a8bcfbdec9 | 52 | int get_binline_by_num(char* filename, int linenum){ |
liangzhen | 0:84a8bcfbdec9 | 53 | char value[30]; |
liangzhen | 0:84a8bcfbdec9 | 54 | |
liangzhen | 0:84a8bcfbdec9 | 55 | //pc.printf("Opening %s File\r\n", filename); |
liangzhen | 0:84a8bcfbdec9 | 56 | FILE *fp = fopen(filename, "r"); |
liangzhen | 0:84a8bcfbdec9 | 57 | if(!fp){ |
liangzhen | 0:84a8bcfbdec9 | 58 | pc.printf("ERROR: %s not found\r\n", filename); |
liangzhen | 0:84a8bcfbdec9 | 59 | } |
liangzhen | 0:84a8bcfbdec9 | 60 | //pc.printf("%s Open\r\n", filename); |
liangzhen | 0:84a8bcfbdec9 | 61 | |
liangzhen | 0:84a8bcfbdec9 | 62 | int i=1; |
liangzhen | 0:84a8bcfbdec9 | 63 | char lineval[255]; |
liangzhen | 0:84a8bcfbdec9 | 64 | while (!feof(fp)) { |
liangzhen | 0:84a8bcfbdec9 | 65 | fscanf(fp, "%s", lineval); |
liangzhen | 0:84a8bcfbdec9 | 66 | if(i == linenum){ |
liangzhen | 0:84a8bcfbdec9 | 67 | strcpy(value, lineval); |
liangzhen | 0:84a8bcfbdec9 | 68 | break; |
liangzhen | 0:84a8bcfbdec9 | 69 | } |
liangzhen | 0:84a8bcfbdec9 | 70 | i++; |
liangzhen | 0:84a8bcfbdec9 | 71 | } |
liangzhen | 0:84a8bcfbdec9 | 72 | |
liangzhen | 0:84a8bcfbdec9 | 73 | //pc.printf("Closing %s File\r\n", filename); |
liangzhen | 0:84a8bcfbdec9 | 74 | fclose(fp); |
liangzhen | 0:84a8bcfbdec9 | 75 | //pc.printf("File %s Closed\r\n", filename); |
liangzhen | 0:84a8bcfbdec9 | 76 | |
liangzhen | 0:84a8bcfbdec9 | 77 | return strtol(value, NULL, 2); |
liangzhen | 0:84a8bcfbdec9 | 78 | } |
liangzhen | 0:84a8bcfbdec9 | 79 | |
liangzhen | 0:84a8bcfbdec9 | 80 | void scan_pll(unsigned int prediv, unsigned int multint_upper, unsigned int multint, |
liangzhen | 0:84a8bcfbdec9 | 81 | unsigned int range_upper, unsigned int rangea, unsigned int rangeb){ |
liangzhen | 0:84a8bcfbdec9 | 82 | |
liangzhen | 0:84a8bcfbdec9 | 83 | prediv = get_binline_by_num("/local/Pprediv.txt", prediv); |
liangzhen | 0:84a8bcfbdec9 | 84 | multint_upper = get_binline_by_num("/local/Pmultup.txt", multint_upper); |
liangzhen | 0:84a8bcfbdec9 | 85 | multint = get_binline_by_num("/local/Pmultint.txt", multint); |
liangzhen | 0:84a8bcfbdec9 | 86 | range_upper = get_binline_by_num("/local/Prangeup.txt", range_upper); |
liangzhen | 0:84a8bcfbdec9 | 87 | rangea = get_binline_by_num("/local/Prange.txt", rangea); |
liangzhen | 0:84a8bcfbdec9 | 88 | rangeb = get_binline_by_num("/local/Prange.txt", rangeb); |
liangzhen | 0:84a8bcfbdec9 | 89 | |
liangzhen | 0:84a8bcfbdec9 | 90 | set_scan_bits("PLL_CE1CCB", 1); |
liangzhen | 0:84a8bcfbdec9 | 91 | set_scan_bits("PLL_CE1MPGC1", 1); |
liangzhen | 0:84a8bcfbdec9 | 92 | set_scan_bits("PLL_FFTUNE", fftune(0)); |
liangzhen | 0:84a8bcfbdec9 | 93 | set_scan_bits("PLL_LFTUNE", lftune()); // @@@ Fix this. Scan doesn't support more than 32 bits |
liangzhen | 0:84a8bcfbdec9 | 94 | set_scan_bits("PLL_INTFBK", 1); |
liangzhen | 0:84a8bcfbdec9 | 95 | set_scan_bits("PLL_PREDIV", prediv); |
liangzhen | 0:84a8bcfbdec9 | 96 | set_scan_bits("PLL_MULTINT", multint_upper << 8 | multint); |
liangzhen | 0:84a8bcfbdec9 | 97 | set_scan_bits("PLL_RANGEA", range_upper << 5 | rangea); |
liangzhen | 0:84a8bcfbdec9 | 98 | set_scan_bits("PLL_RANGEB", range_upper << 5 | rangeb); |
liangzhen | 0:84a8bcfbdec9 | 99 | } |
liangzhen | 0:84a8bcfbdec9 | 100 | |
liangzhen | 0:84a8bcfbdec9 | 101 | void jtag_pll(JTAG &jtag, unsigned int prediv, unsigned int multint_upper, unsigned int multint, |
liangzhen | 0:84a8bcfbdec9 | 102 | unsigned int range_upper, unsigned int rangea, unsigned int rangeb){ |
liangzhen | 0:84a8bcfbdec9 | 103 | |
liangzhen | 0:84a8bcfbdec9 | 104 | prediv = get_binline_by_num("/local/Pprediv.txt", prediv); |
liangzhen | 0:84a8bcfbdec9 | 105 | multint_upper = get_binline_by_num("/local/Pmultup.txt", multint_upper); |
liangzhen | 0:84a8bcfbdec9 | 106 | multint = get_binline_by_num("/local/Pmultint.txt", multint); |
liangzhen | 0:84a8bcfbdec9 | 107 | range_upper = get_binline_by_num("/local/Prangeup.txt", range_upper); |
liangzhen | 0:84a8bcfbdec9 | 108 | rangea = get_binline_by_num("/local/Prange.txt", rangea); |
liangzhen | 0:84a8bcfbdec9 | 109 | rangeb = get_binline_by_num("/local/Prange.txt", rangeb); |
liangzhen | 0:84a8bcfbdec9 | 110 | jtag.writeMemory(PLL_CE1CCB, 1); |
liangzhen | 0:84a8bcfbdec9 | 111 | jtag.writeMemory(PLL_CE1MPGC1, 1); |
liangzhen | 0:84a8bcfbdec9 | 112 | jtag.writeMemory(PLL_FFTUNE, fftune(0)); |
liangzhen | 0:84a8bcfbdec9 | 113 | jtag.writeMemory(PLL_LFTUNE_32_0, lftune_lo()); |
liangzhen | 0:84a8bcfbdec9 | 114 | jtag.writeMemory(PLL_LFTUNE_40_32, lftune_hi()); |
liangzhen | 0:84a8bcfbdec9 | 115 | jtag.writeMemory(PLL_INTFBK, 1); |
liangzhen | 0:84a8bcfbdec9 | 116 | jtag.writeMemory(PLL_PREDIV, prediv); |
liangzhen | 0:84a8bcfbdec9 | 117 | jtag.writeMemory(PLL_RANGEA, range_upper << 5 | rangea); |
liangzhen | 0:84a8bcfbdec9 | 118 | jtag.writeMemory(PLL_RANGEB, range_upper << 5 | rangeb); |
liangzhen | 1:6a820a0ca03b | 119 | jtag.writeMemory(PLL_MULTINT, multint_upper << 8 | multint); |
liangzhen | 0:84a8bcfbdec9 | 120 | } |
liangzhen | 0:84a8bcfbdec9 | 121 | |
liangzhen | 0:84a8bcfbdec9 | 122 | |
liangzhen | 0:84a8bcfbdec9 | 123 | unsigned int fftune(bool change_rangeab){ |
liangzhen | 0:84a8bcfbdec9 | 124 | if(change_rangeab){ |
liangzhen | 0:84a8bcfbdec9 | 125 | return 0x0120; |
liangzhen | 0:84a8bcfbdec9 | 126 | }else{ |
liangzhen | 0:84a8bcfbdec9 | 127 | return 0x0100; |
liangzhen | 0:84a8bcfbdec9 | 128 | } |
liangzhen | 0:84a8bcfbdec9 | 129 | } |
liangzhen | 0:84a8bcfbdec9 | 130 | |
liangzhen | 0:84a8bcfbdec9 | 131 | unsigned int lftune_hi(){ |
liangzhen | 0:84a8bcfbdec9 | 132 | return 0x00000050; |
liangzhen | 0:84a8bcfbdec9 | 133 | } |
liangzhen | 0:84a8bcfbdec9 | 134 | |
liangzhen | 0:84a8bcfbdec9 | 135 | unsigned int lftune_lo(){ |
liangzhen | 0:84a8bcfbdec9 | 136 | return 0x40100000; |
liangzhen | 0:84a8bcfbdec9 | 137 | } |
liangzhen | 0:84a8bcfbdec9 | 138 | |
liangzhen | 0:84a8bcfbdec9 | 139 | unsigned long long lftune(){ |
liangzhen | 0:84a8bcfbdec9 | 140 | // 41 bits |
liangzhen | 0:84a8bcfbdec9 | 141 | return 0x05040100000L; |
liangzhen | 1:6a820a0ca03b | 142 | } |
liangzhen | 1:6a820a0ca03b | 143 | |
liangzhen | 1:6a820a0ca03b | 144 | /* |
liangzhen | 1:6a820a0ca03b | 145 | unsigned long long calc_pll_freqs(unsigned int prediv, unsigned int multint_upper, unsigned int multint, |
liangzhen | 1:6a820a0ca03b | 146 | unsigned int range_upper, unsigned int rangea, unsigned int rangeb) |
liangzhen | 1:6a820a0ca03b | 147 | dco = (PLL_REF / prediv) * multint_upper * multint; |
liangzhen | 1:6a820a0ca03b | 148 | prescale_dco = dco / range_upper; |
liangzhen | 1:6a820a0ca03b | 149 | out_a = prescale_dco / rangea; |
liangzhen | 1:6a820a0ca03b | 150 | */ |
liangzhen | 1:6a820a0ca03b | 151 | int set_pll_frequency (int fMHz, JTAG &jtag) { |
liangzhen | 1:6a820a0ca03b | 152 | jtag.writeMemory(intclk_source, 0); |
liangzhen | 1:6a820a0ca03b | 153 | int counter = fMHz / 5; |
liangzhen | 1:6a820a0ca03b | 154 | int frequency = counter * 5; |
liangzhen | 1:6a820a0ca03b | 155 | if (frequency >= 625) { |
liangzhen | 1:6a820a0ca03b | 156 | pc.printf("Frequency > 625 MHz out of range!\r\nClock source changed to HCLK_EXT\r\n"); |
liangzhen | 1:6a820a0ca03b | 157 | return 1; |
liangzhen | 1:6a820a0ca03b | 158 | } /* |
liangzhen | 1:6a820a0ca03b | 159 | else if (frequency >= 625) { |
liangzhen | 1:6a820a0ca03b | 160 | //counter between 125 and 200 |
liangzhen | 1:6a820a0ca03b | 161 | // 20*125/4=625 |
liangzhen | 1:6a820a0ca03b | 162 | // 20*200/4=1G |
liangzhen | 1:6a820a0ca03b | 163 | jtag_pll(jtag, 1, 1, counter, 1, 4, 4); |
liangzhen | 1:6a820a0ca03b | 164 | calculated_f = calc_pll_freqs(1, 1, counter, 1, 4, 4)/1000; |
liangzhen | 1:6a820a0ca03b | 165 | if (calculated_f != frequency) { |
liangzhen | 1:6a820a0ca03b | 166 | pc.printf("PLL frequency not match!\r\n"); |
liangzhen | 1:6a820a0ca03b | 167 | } |
liangzhen | 1:6a820a0ca03b | 168 | } */ |
liangzhen | 1:6a820a0ca03b | 169 | else if (frequency >= 325) { |
liangzhen | 1:6a820a0ca03b | 170 | //counter between 65 and 125 |
liangzhen | 1:6a820a0ca03b | 171 | // 20*2*65/8=325 |
liangzhen | 1:6a820a0ca03b | 172 | // 20*2*125/8=625 |
liangzhen | 1:6a820a0ca03b | 173 | jtag_pll(jtag, 1, 2, counter, 1, 8, 8); |
liangzhen | 1:6a820a0ca03b | 174 | } else if (frequency >= 210) { |
liangzhen | 1:6a820a0ca03b | 175 | //counter between 42 and 65 |
liangzhen | 1:6a820a0ca03b | 176 | // 20*3*42/12=210 |
liangzhen | 1:6a820a0ca03b | 177 | // 20*3*65/12=325 |
liangzhen | 1:6a820a0ca03b | 178 | jtag_pll(jtag, 1, 3, counter, 1, 12, 12); |
liangzhen | 1:6a820a0ca03b | 179 | } else if (frequency >= 105) { |
liangzhen | 1:6a820a0ca03b | 180 | //counter between 21 and 42 |
liangzhen | 1:6a820a0ca03b | 181 | // 20*6*21/24=125 |
liangzhen | 1:6a820a0ca03b | 182 | // 20*6*42/24=210 |
liangzhen | 1:6a820a0ca03b | 183 | jtag_pll(jtag, 1, 3, 2*counter, 1, 24, 24); |
liangzhen | 1:6a820a0ca03b | 184 | } else { |
liangzhen | 1:6a820a0ca03b | 185 | pc.printf("Frequency < 105M out of range!\r\nClock source changed to HCLK_EXT\r\n"); |
liangzhen | 1:6a820a0ca03b | 186 | return 1; |
liangzhen | 1:6a820a0ca03b | 187 | } |
liangzhen | 1:6a820a0ca03b | 188 | jtag.writeMemory(PLL_RESET, 1); |
liangzhen | 1:6a820a0ca03b | 189 | wait_us(10); |
liangzhen | 1:6a820a0ca03b | 190 | jtag.writeMemory(PLL_RESET, 0); |
liangzhen | 1:6a820a0ca03b | 191 | wait_us(10); |
liangzhen | 1:6a820a0ca03b | 192 | if(jtag.readMemory(PLL_PLLLOCK)==0) { |
liangzhen | 1:6a820a0ca03b | 193 | pc.printf("PLL lock failed!\r\nClock source changed to HCLK_EXT\r\n"); |
liangzhen | 1:6a820a0ca03b | 194 | return 1; |
liangzhen | 1:6a820a0ca03b | 195 | } else { |
liangzhen | 1:6a820a0ca03b | 196 | jtag.writeMemory(intclk_source, 2); |
liangzhen | 1:6a820a0ca03b | 197 | return 0; |
liangzhen | 1:6a820a0ca03b | 198 | } |
liangzhen | 0:84a8bcfbdec9 | 199 | } |