int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) { SPI_Type *spi_dev; uint8_t br_prescaler = 0xff; uint8_t br_scaler = 0xff; uint8_t prescaler_tmp = 0xff; uint8_t scaler_tmp = 0xff; uint32_t ctas = 0; uint32_t ctar = 0; uint32_t br_desired; uint32_t module_clock; uint32_t tcsc_freq; uint32_t tasc_freq; uint32_t tdt_freq; switch (speed) { case SPI_SPEED_100KHZ: br_desired = 100000; break; case SPI_SPEED_400KHZ: br_desired = 400000; break; case SPI_SPEED_1MHZ: br_desired = 1000000; break; case SPI_SPEED_5MHZ: br_desired = 5000000; break; case SPI_SPEED_10MHZ: br_desired = 10000000; break; default: return -2; } switch (dev) { #if SPI_0_EN case SPI_0: KINETIS_CFG_SPI_IO(0); break; #endif /* SPI_0_EN */ #if SPI_1_EN case SPI_1: KINETIS_CFG_SPI_IO(1); break; #endif /* SPI_1_EN */ #if SPI_2_EN case SPI_2: KINETIS_CFG_SPI_IO(2); break; #endif /* SPI_2_EN */ #if SPI_3_EN case SPI_3: KINETIS_CFG_SPI_IO(3); break; #endif /* SPI_3_EN */ #if SPI_4_EN case SPI_4: KINETIS_CFG_SPI_IO(4); break; #endif /* SPI_4_EN */ #if SPI_5_EN case SPI_5: KINETIS_CFG_SPI_IO(5); break; #endif /* SPI_5_EN */ #if SPI_6_EN case SPI_6: KINETIS_CFG_SPI_IO(6); break; #endif /* SPI_6_EN */ #if SPI_7_EN case SPI_7: KINETIS_CFG_SPI_IO(7); break; #endif /* SPI_7_EN */ default: return -1; } /* Find baud rate scaler and prescaler settings */ if (find_closest_baudrate_scalers(module_clock, br_desired, &br_prescaler, &br_scaler) < 0) { /* Desired baud rate is too low to be reachable at current module clock frequency. */ return -2; } ctar |= SPI_CTAR_PBR(br_prescaler) | SPI_CTAR_BR(br_scaler); /* Find the other delay divisors */ /* tCSC */ if (tcsc_freq == 0) { /* Default to same as baud rate if set to zero. */ tcsc_freq = br_desired; } if (find_closest_delay_scalers(module_clock, tcsc_freq, &prescaler_tmp, &scaler_tmp) < 0) { /* failed to find a solution */ return -2; } ctar |= SPI_CTAR_PCSSCK(prescaler_tmp) | SPI_CTAR_CSSCK(scaler_tmp); /* tASC */ if (tasc_freq == 0) { /* Default to same as baud rate if set to zero. */ tasc_freq = br_desired; } if (find_closest_delay_scalers(module_clock, tasc_freq, &prescaler_tmp, &scaler_tmp) < 0) { /* failed to find a solution */ return -2; } ctar |= SPI_CTAR_PASC(prescaler_tmp) | SPI_CTAR_ASC(scaler_tmp); /* tDT */ if (tdt_freq == 0) { /* Default to same as baud rate if set to zero. */ tdt_freq = br_desired; } if (find_closest_delay_scalers(module_clock, tdt_freq, &prescaler_tmp, &scaler_tmp) < 0) { /* failed to find a solution */ return -2; } ctar |= SPI_CTAR_PDT(prescaler_tmp) | SPI_CTAR_DT(scaler_tmp); /* Set clock polarity and phase. */ switch (conf) { case SPI_CONF_FIRST_RISING: break; case SPI_CONF_SECOND_RISING: ctar |= SPI_CTAR_CPHA_MASK; break; case SPI_CONF_FIRST_FALLING: ctar |= SPI_CTAR_CPOL_MASK; break; case SPI_CONF_SECOND_FALLING: ctar |= SPI_CTAR_CPHA_MASK | SPI_CTAR_CPOL_MASK; break; default: return -2; } /* Update CTAR register with new timing settings, 8-bit frame size. */ spi_dev->CTAR[ctas] = SPI_CTAR_FMSZ(7) | ctar; /* enable SPI */ spi_dev->MCR = SPI_MCR_MSTR_MASK | SPI_MCR_DOZE_MASK | SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK; if (KINETIS_SPI_USE_HW_CS) { spi_dev->MCR |= SPI_MCR_PCSIS(1); } spi_dev->RSER = (uint32_t)0; return 0; }
void spi_set_params(const spi_bus_t spi_num, const uint8_t ctas, const spi_config_t* config) { uint32_t ctar = 0; uint8_t br_prescaler = 0xff; uint8_t br_scaler = 0xff; uint8_t prescaler_tmp = 0xff; uint8_t scaler_tmp = 0xff; /* All of the SPI modules run on the Bus clock, see K60 Ref Manual. 3.9.4.2 SPI clocking */ /* Find the baud rate divisors */ find_closest_baudrate_scalers(SystemBusClock, config->sck_freq, &br_prescaler, &br_scaler); ctar |= SPI_CTAR_PBR(br_prescaler) | SPI_CTAR_BR(br_scaler); /* Find the other delay divisors */ /* tCSC */ if (config->tcsc_freq > 0) { if (find_closest_delay_scalers(SystemBusClock, config->tcsc_freq, &prescaler_tmp, &scaler_tmp) == 0) { ctar |= SPI_CTAR_PCSSCK(prescaler_tmp) | SPI_CTAR_CSSCK(scaler_tmp); } else { /* failed to find a solution */ DEBUGGER_BREAK(BREAK_INVALID_PARAM); } } else { /* default: copy BR scaler */ ctar |= SPI_CTAR_PCSSCK(br_prescaler) | SPI_CTAR_CSSCK(br_scaler); } /* tASC */ if (config->tasc_freq > 0) { if (find_closest_delay_scalers(SystemBusClock, config->tasc_freq, &prescaler_tmp, &scaler_tmp) == 0) { ctar |= SPI_CTAR_PASC(prescaler_tmp) | SPI_CTAR_ASC(scaler_tmp); } else { /* failed to find a solution */ DEBUGGER_BREAK(BREAK_INVALID_PARAM); } } else { /* default: copy BR scaler */ ctar |= SPI_CTAR_PASC(br_prescaler) | SPI_CTAR_ASC(br_scaler); } /* tDT */ if (config->tdt_freq > 0) { if (find_closest_delay_scalers(SystemBusClock, config->tdt_freq, &prescaler_tmp, &scaler_tmp) == 0) { ctar |= SPI_CTAR_PDT(prescaler_tmp) | SPI_CTAR_DT(scaler_tmp); } else { /* failed to find a solution */ DEBUGGER_BREAK(BREAK_INVALID_PARAM); } } else { /* default: copy BR scaler */ ctar |= SPI_CTAR_PDT(br_prescaler) | SPI_CTAR_DT(br_scaler); } /* FMSZ+1 equals the frame size */ ctar |= SPI_CTAR_FMSZ(config->frame_size - 1); if (config->cpol != 0) { ctar |= SPI_CTAR_CPOL_MASK; } if (config->cpha != 0) { ctar |= SPI_CTAR_CPHA_MASK; } SPI[spi_num]->CTAR[ctas] = ctar; spi_conf[spi_num][ctas] = config; }
int main(int argc, char **argv) { uint32_t modclk; int i; if (argc != 2) { printf("usage: %s <module clock>\n", argv[0]); return 1; } modclk = atoi(argv[1]); if (modclk == 0) { printf("error: invalid input value\n"); return 1; } printf("\nCalculating SPI clock scalers for a module clock of: %iHz\n\n", (int)modclk); puts("static const uint32_t spi_clk_config[] = {"); for (i = 0; i < (sizeof(targets) / sizeof(targets[0])); i++) { uint8_t tmp, ptmp; long res; /* bus clock */ res = find_closest_baudrate_scalers(modclk, targets[i], &ptmp, &tmp); if (res < 0) { puts("error: no applicable bus clock scalers could be found!"); return 1; } puts(" ("); printf(" SPI_CTAR_PBR(%i) | SPI_CTAR_BR(%i) | /* -> %iHz */\n", (int)ptmp, (int)tmp, (int)res); /* t_csc: chip select to fist clock signal delay */ if (find_closest_delay_scalers(modclk, targets[i], &ptmp, &tmp) < 0) { puts("error: no applicable delay values for t_csc found\n"); return 1; } printf(" SPI_CTAR_PCSSCK(%i) | SPI_CTAR_CSSCK(%i) |\n", (int)ptmp, (int)tmp); /* t_asc: delay after last clock signal to release of chip select */ if (find_closest_delay_scalers(modclk, targets[i], &ptmp, &tmp) < 0) { puts("error: no applicable delay values for t_asc found\n"); return 1; } printf(" SPI_CTAR_PASC(%i) | SPI_CTAR_ASC(%i) |\n", (int)ptmp, (int)tmp); /* t_psc: delay between release and next assertion of chip select */ if (find_closest_delay_scalers(modclk, targets[i], &ptmp, &tmp) < 0) { puts("error: no applicable delay values for t_csc found\n"); return 1; } printf(" SPI_CTAR_PDT(%i) | SPI_CTAR_DT(%i)\n", (int)ptmp, (int)tmp); if (i == (sizeof(targets) / sizeof(targets[0])) - 1) { puts(" )"); } else { puts(" ),"); } } puts("};"); return 0; }