mbed library sources
Dependents: FRDM-KL46Z_LCD_Test FRDM-KL46Z_LCD_Test FRDM-KL46Z_Plantilla FRDM-KL46Z_Plantilla ... more
targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/spi_api.c@0:6bc4ac881c8e, 2016-07-28 (annotated)
- Committer:
- ebrus
- Date:
- Thu Jul 28 15:56:34 2016 +0000
- Revision:
- 0:6bc4ac881c8e
1;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ebrus | 0:6bc4ac881c8e | 1 | /* mbed Microcontroller Library |
ebrus | 0:6bc4ac881c8e | 2 | * Copyright (c) 2013 ARM Limited |
ebrus | 0:6bc4ac881c8e | 3 | * |
ebrus | 0:6bc4ac881c8e | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
ebrus | 0:6bc4ac881c8e | 5 | * you may not use this file except in compliance with the License. |
ebrus | 0:6bc4ac881c8e | 6 | * You may obtain a copy of the License at |
ebrus | 0:6bc4ac881c8e | 7 | * |
ebrus | 0:6bc4ac881c8e | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
ebrus | 0:6bc4ac881c8e | 9 | * |
ebrus | 0:6bc4ac881c8e | 10 | * Unless required by applicable law or agreed to in writing, software |
ebrus | 0:6bc4ac881c8e | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
ebrus | 0:6bc4ac881c8e | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
ebrus | 0:6bc4ac881c8e | 13 | * See the License for the specific language governing permissions and |
ebrus | 0:6bc4ac881c8e | 14 | * limitations under the License. |
ebrus | 0:6bc4ac881c8e | 15 | */ |
ebrus | 0:6bc4ac881c8e | 16 | #include <math.h> |
ebrus | 0:6bc4ac881c8e | 17 | #include "mbed_assert.h" |
ebrus | 0:6bc4ac881c8e | 18 | |
ebrus | 0:6bc4ac881c8e | 19 | #include "spi_api.h" |
ebrus | 0:6bc4ac881c8e | 20 | |
ebrus | 0:6bc4ac881c8e | 21 | #if DEVICE_SPI |
ebrus | 0:6bc4ac881c8e | 22 | |
ebrus | 0:6bc4ac881c8e | 23 | #include "cmsis.h" |
ebrus | 0:6bc4ac881c8e | 24 | #include "pinmap.h" |
ebrus | 0:6bc4ac881c8e | 25 | #include "mbed_error.h" |
ebrus | 0:6bc4ac881c8e | 26 | #include "fsl_clock_manager.h" |
ebrus | 0:6bc4ac881c8e | 27 | #include "fsl_dspi_hal.h" |
ebrus | 0:6bc4ac881c8e | 28 | #include "PeripheralPins.h" |
ebrus | 0:6bc4ac881c8e | 29 | |
ebrus | 0:6bc4ac881c8e | 30 | void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { |
ebrus | 0:6bc4ac881c8e | 31 | // determine the SPI to use |
ebrus | 0:6bc4ac881c8e | 32 | uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI); |
ebrus | 0:6bc4ac881c8e | 33 | uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO); |
ebrus | 0:6bc4ac881c8e | 34 | uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK); |
ebrus | 0:6bc4ac881c8e | 35 | uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL); |
ebrus | 0:6bc4ac881c8e | 36 | uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso); |
ebrus | 0:6bc4ac881c8e | 37 | uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel); |
ebrus | 0:6bc4ac881c8e | 38 | |
ebrus | 0:6bc4ac881c8e | 39 | obj->instance = pinmap_merge(spi_data, spi_cntl); |
ebrus | 0:6bc4ac881c8e | 40 | MBED_ASSERT((int)obj->instance != NC); |
ebrus | 0:6bc4ac881c8e | 41 | |
ebrus | 0:6bc4ac881c8e | 42 | CLOCK_SYS_EnableSpiClock(obj->instance); |
ebrus | 0:6bc4ac881c8e | 43 | uint32_t spi_address[] = SPI_BASE_ADDRS; |
ebrus | 0:6bc4ac881c8e | 44 | DSPI_HAL_Init(spi_address[obj->instance]); |
ebrus | 0:6bc4ac881c8e | 45 | DSPI_HAL_Disable(spi_address[obj->instance]); |
ebrus | 0:6bc4ac881c8e | 46 | // set default format and frequency |
ebrus | 0:6bc4ac881c8e | 47 | if (ssel == NC) { |
ebrus | 0:6bc4ac881c8e | 48 | spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master |
ebrus | 0:6bc4ac881c8e | 49 | } else { |
ebrus | 0:6bc4ac881c8e | 50 | spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave |
ebrus | 0:6bc4ac881c8e | 51 | } |
ebrus | 0:6bc4ac881c8e | 52 | DSPI_HAL_SetDelay(spi_address[obj->instance], kDspiCtar0, 0, 0, kDspiPcsToSck); |
ebrus | 0:6bc4ac881c8e | 53 | spi_frequency(obj, 1000000); |
ebrus | 0:6bc4ac881c8e | 54 | |
ebrus | 0:6bc4ac881c8e | 55 | DSPI_HAL_Enable(spi_address[obj->instance]); |
ebrus | 0:6bc4ac881c8e | 56 | DSPI_HAL_StartTransfer(spi_address[obj->instance]); |
ebrus | 0:6bc4ac881c8e | 57 | |
ebrus | 0:6bc4ac881c8e | 58 | // pin out the spi pins |
ebrus | 0:6bc4ac881c8e | 59 | pinmap_pinout(mosi, PinMap_SPI_MOSI); |
ebrus | 0:6bc4ac881c8e | 60 | pinmap_pinout(miso, PinMap_SPI_MISO); |
ebrus | 0:6bc4ac881c8e | 61 | pinmap_pinout(sclk, PinMap_SPI_SCLK); |
ebrus | 0:6bc4ac881c8e | 62 | if (ssel != NC) { |
ebrus | 0:6bc4ac881c8e | 63 | pinmap_pinout(ssel, PinMap_SPI_SSEL); |
ebrus | 0:6bc4ac881c8e | 64 | } |
ebrus | 0:6bc4ac881c8e | 65 | } |
ebrus | 0:6bc4ac881c8e | 66 | |
ebrus | 0:6bc4ac881c8e | 67 | void spi_free(spi_t *obj) { |
ebrus | 0:6bc4ac881c8e | 68 | // [TODO] |
ebrus | 0:6bc4ac881c8e | 69 | } |
ebrus | 0:6bc4ac881c8e | 70 | void spi_format(spi_t *obj, int bits, int mode, int slave) { |
ebrus | 0:6bc4ac881c8e | 71 | dspi_data_format_config_t config = {0}; |
ebrus | 0:6bc4ac881c8e | 72 | config.bitsPerFrame = (uint32_t)bits; |
ebrus | 0:6bc4ac881c8e | 73 | config.clkPolarity = (mode & 0x2) ? kDspiClockPolarity_ActiveLow : kDspiClockPolarity_ActiveHigh; |
ebrus | 0:6bc4ac881c8e | 74 | config.clkPhase = (mode & 0x1) ? kDspiClockPhase_SecondEdge : kDspiClockPhase_FirstEdge; |
ebrus | 0:6bc4ac881c8e | 75 | config.direction = kDspiMsbFirst; |
ebrus | 0:6bc4ac881c8e | 76 | uint32_t spi_address[] = SPI_BASE_ADDRS; |
ebrus | 0:6bc4ac881c8e | 77 | dspi_status_t result = DSPI_HAL_SetDataFormat(spi_address[obj->instance], kDspiCtar0, &config); |
ebrus | 0:6bc4ac881c8e | 78 | if (result != kStatus_DSPI_Success) { |
ebrus | 0:6bc4ac881c8e | 79 | error("Failed to configure SPI data format"); |
ebrus | 0:6bc4ac881c8e | 80 | } |
ebrus | 0:6bc4ac881c8e | 81 | |
ebrus | 0:6bc4ac881c8e | 82 | if (slave) { |
ebrus | 0:6bc4ac881c8e | 83 | DSPI_HAL_SetMasterSlaveMode(spi_address[obj->instance], kDspiSlave); |
ebrus | 0:6bc4ac881c8e | 84 | } else { |
ebrus | 0:6bc4ac881c8e | 85 | DSPI_HAL_SetMasterSlaveMode(spi_address[obj->instance], kDspiMaster); |
ebrus | 0:6bc4ac881c8e | 86 | } |
ebrus | 0:6bc4ac881c8e | 87 | } |
ebrus | 0:6bc4ac881c8e | 88 | |
ebrus | 0:6bc4ac881c8e | 89 | void spi_frequency(spi_t *obj, int hz) { |
ebrus | 0:6bc4ac881c8e | 90 | uint32_t busClock; |
ebrus | 0:6bc4ac881c8e | 91 | CLOCK_SYS_GetFreq(kBusClock, &busClock); |
ebrus | 0:6bc4ac881c8e | 92 | uint32_t spi_address[] = SPI_BASE_ADDRS; |
ebrus | 0:6bc4ac881c8e | 93 | DSPI_HAL_SetBaudRate(spi_address[obj->instance], kDspiCtar0, (uint32_t)hz, busClock); |
ebrus | 0:6bc4ac881c8e | 94 | } |
ebrus | 0:6bc4ac881c8e | 95 | |
ebrus | 0:6bc4ac881c8e | 96 | static inline int spi_writeable(spi_t * obj) { |
ebrus | 0:6bc4ac881c8e | 97 | uint32_t spi_address[] = SPI_BASE_ADDRS; |
ebrus | 0:6bc4ac881c8e | 98 | return DSPI_HAL_GetStatusFlag(spi_address[obj->instance], kDspiTxFifoFillRequest); |
ebrus | 0:6bc4ac881c8e | 99 | } |
ebrus | 0:6bc4ac881c8e | 100 | |
ebrus | 0:6bc4ac881c8e | 101 | static inline int spi_readable(spi_t * obj) { |
ebrus | 0:6bc4ac881c8e | 102 | uint32_t spi_address[] = SPI_BASE_ADDRS; |
ebrus | 0:6bc4ac881c8e | 103 | return DSPI_HAL_GetStatusFlag(spi_address[obj->instance], kDspiRxFifoDrainRequest); |
ebrus | 0:6bc4ac881c8e | 104 | } |
ebrus | 0:6bc4ac881c8e | 105 | |
ebrus | 0:6bc4ac881c8e | 106 | int spi_master_write(spi_t *obj, int value) { |
ebrus | 0:6bc4ac881c8e | 107 | uint32_t spi_address[] = SPI_BASE_ADDRS; |
ebrus | 0:6bc4ac881c8e | 108 | |
ebrus | 0:6bc4ac881c8e | 109 | // wait tx buffer empty |
ebrus | 0:6bc4ac881c8e | 110 | while(!spi_writeable(obj)); |
ebrus | 0:6bc4ac881c8e | 111 | dspi_command_config_t command = {0}; |
ebrus | 0:6bc4ac881c8e | 112 | command.isEndOfQueue = true; |
ebrus | 0:6bc4ac881c8e | 113 | command.isChipSelectContinuous = 0; |
ebrus | 0:6bc4ac881c8e | 114 | DSPI_HAL_WriteDataMastermode(spi_address[obj->instance], &command, (uint16_t)value); |
ebrus | 0:6bc4ac881c8e | 115 | DSPI_HAL_ClearStatusFlag(spi_address[obj->instance], kDspiTxFifoFillRequest); |
ebrus | 0:6bc4ac881c8e | 116 | |
ebrus | 0:6bc4ac881c8e | 117 | // wait rx buffer full |
ebrus | 0:6bc4ac881c8e | 118 | while (!spi_readable(obj)); |
ebrus | 0:6bc4ac881c8e | 119 | DSPI_HAL_ClearStatusFlag(spi_address[obj->instance], kDspiRxFifoDrainRequest); |
ebrus | 0:6bc4ac881c8e | 120 | return DSPI_HAL_ReadData(spi_address[obj->instance]) & 0xff; |
ebrus | 0:6bc4ac881c8e | 121 | } |
ebrus | 0:6bc4ac881c8e | 122 | |
ebrus | 0:6bc4ac881c8e | 123 | int spi_slave_receive(spi_t *obj) { |
ebrus | 0:6bc4ac881c8e | 124 | return spi_readable(obj); |
ebrus | 0:6bc4ac881c8e | 125 | } |
ebrus | 0:6bc4ac881c8e | 126 | |
ebrus | 0:6bc4ac881c8e | 127 | int spi_slave_read(spi_t *obj) { |
ebrus | 0:6bc4ac881c8e | 128 | DSPI_HAL_ClearStatusFlag(obj->instance, kDspiRxFifoDrainRequest); |
ebrus | 0:6bc4ac881c8e | 129 | uint32_t spi_address[] = SPI_BASE_ADDRS; |
ebrus | 0:6bc4ac881c8e | 130 | return DSPI_HAL_ReadData(spi_address[obj->instance]); |
ebrus | 0:6bc4ac881c8e | 131 | } |
ebrus | 0:6bc4ac881c8e | 132 | |
ebrus | 0:6bc4ac881c8e | 133 | void spi_slave_write(spi_t *obj, int value) { |
ebrus | 0:6bc4ac881c8e | 134 | while (!spi_writeable(obj)); |
ebrus | 0:6bc4ac881c8e | 135 | uint32_t spi_address[] = SPI_BASE_ADDRS; |
ebrus | 0:6bc4ac881c8e | 136 | DSPI_HAL_WriteDataSlavemode(spi_address[obj->instance], (uint32_t)value); |
ebrus | 0:6bc4ac881c8e | 137 | } |
ebrus | 0:6bc4ac881c8e | 138 | |
ebrus | 0:6bc4ac881c8e | 139 | #endif |