Exemple #1
0
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;
}
Exemple #2
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;
}
Exemple #3
0
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;
}