Skip to content

K20D5(0)M SPI code #311

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 19, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 23 additions & 29 deletions libraries/mbed/targets/hal/TARGET_Freescale/TARGET_K20D5M/spi_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);

obj->spi = (SPI_Type*)pinmap_merge(spi_data, spi_cntl);
if ((int)obj->spi == NC) {
error("SPI pinout mapping failed");
Expand All @@ -63,9 +63,8 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK;
SIM->SCGC6 |= SIM_SCGC6_SPI0_MASK;

// halted state
obj->spi->MCR &= ~SPI_MCR_MDIS_MASK;
obj->spi->MCR |= SPI_MCR_HALT_MASK | SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK;
obj->spi->MCR &= ~(SPI_MCR_MDIS_MASK | SPI_MCR_HALT_MASK);
//obj->spi->MCR |= SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK;

// set default format and frequency
if (ssel == NC) {
Expand All @@ -77,8 +76,6 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel

// not halt in the debug mode
obj->spi->SR |= SPI_SR_EOQF_MASK;
// enable SPI
obj->spi->MCR &= (~SPI_MCR_HALT_MASK);

// pin out the spi pins
pinmap_pinout(mosi, PinMap_SPI_MOSI);
Expand All @@ -93,9 +90,9 @@ void spi_free(spi_t *obj) {
// [TODO]
}
void spi_format(spi_t *obj, int bits, int mode, int slave) {
if ((bits != 8) && (bits != 16)) {
error("Only 8/16 bits SPI supported");
}
if ((bits < 4) || (bits > 16))
error("SPI: Only frames between 4 and 16-bit supported");


if ((mode < 0) || (mode > 3)) {
error("SPI mode unsupported");
Expand All @@ -109,64 +106,61 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) {
obj->spi->MCR |= ((!slave) << SPI_MCR_MSTR_SHIFT);

// CTAR0 is used
obj->spi->CTAR[0] &= ~(SPI_CTAR_CPHA_MASK | SPI_CTAR_CPOL_MASK);
obj->spi->CTAR[0] |= (polarity << SPI_CTAR_CPOL_SHIFT) | (phase << SPI_CTAR_CPHA_SHIFT);
obj->spi->CTAR[0] &= ~(SPI_CTAR_CPHA_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_FMSZ_MASK);
obj->spi->CTAR[0] |= (polarity << SPI_CTAR_CPOL_SHIFT) | (phase << SPI_CTAR_CPHA_SHIFT) | ((bits - 1) << SPI_CTAR_FMSZ_SHIFT);
}

static const uint8_t baudrate_prescaler[] = {2,3,5,7};
static const uint32_t baudrate_scaler[] = {2, 4, 6, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
static const uint8_t delay_prescaler[] = {1, 3, 5, 7};
static const uint16_t baudrate_scaler[] = {2,4,6,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};

void spi_frequency(spi_t *obj, int hz) {
uint32_t error = 0;
uint32_t f_error = 0;
uint32_t p_error = 0xffffffff;
uint32_t ref = 0;
uint32_t br = 0;
uint32_t ref_spr = 0;
uint32_t ref_prescaler = 0;
uint32_t ref_dr = 0;

// bus clk
uint32_t PCLK = bus_frequency();
uint32_t divisor = 2;
uint32_t prescaler;

/* TODO */
for (uint32_t i = 0; i < 4; i++) {
prescaler = baudrate_prescaler[i];
divisor = 2;
for (br = 0; br <= 15; br++, divisor *= 2) {
for (br = 0; br <= 15; br++) {
for (uint32_t dr = 0; dr < 2; dr++) {
ref = (PCLK / prescaler) * ((1U + dr) / divisor);
ref = (PCLK * (1U + dr) / baudrate_prescaler[i]) / baudrate_scaler[br];
if (ref > (uint32_t)hz)
continue;
error = hz - ref;
if (error < p_error) {
f_error = hz - ref;
if (f_error < p_error) {
ref_spr = br;
ref_prescaler = i;
p_error = error;
ref_dr = dr;
p_error = f_error;
}
}
}
}

// set PBR and BR
obj->spi->CTAR[0] = ((ref_prescaler & 0x3) << SPI_CTAR_PBR_SHIFT) | (ref_spr & 0xf);
obj->spi->CTAR[0] &= ~(SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK | SPI_CTAR_DBR_MASK);
obj->spi->CTAR[0] |= (ref_prescaler << SPI_CTAR_PBR_SHIFT) | (ref_spr << SPI_CTAR_BR_SHIFT) | (ref_dr << SPI_CTAR_DBR_SHIFT);
}

static inline int spi_writeable(spi_t *obj) {
return (obj->spi->SR & SPI_SR_TFFF_MASK) ? 1 : 0;
}

static inline int spi_readable(spi_t *obj) {
return (obj->spi->SR & SPI_SR_RFDF_MASK) ? 0 : 1;
return (obj->spi->SR & SPI_SR_RFDF_MASK) ? 1 : 0;
}

int spi_master_write(spi_t *obj, int value) {
//clear RX buffer flag
obj->spi->SR |= SPI_SR_RFDF_MASK;
// wait tx buffer empty
while(!spi_writeable(obj));
obj->spi->PUSHR = SPI_PUSHR_TXDATA(value & 0xff) /*| SPI_PUSHR_EOQ_MASK*/;

while (!obj->spi->SR & SPI_SR_TCF_MASK); // wait for transfer to be complete
obj->spi->PUSHR = SPI_PUSHR_TXDATA(value & 0xffff) /*| SPI_PUSHR_EOQ_MASK*/;

// wait rx buffer full
while (!spi_readable(obj));
Expand Down