![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466
mbed-os/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/spi_api.c@3:f3764f852aa8, 2018-10-11 (annotated)
- Committer:
- kadonotakashi
- Date:
- Thu Oct 11 02:27:46 2018 +0000
- Revision:
- 3:f3764f852aa8
- Parent:
- 0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kadonotakashi | 0:8fdf9a60065b | 1 | /* mbed Microcontroller Library |
kadonotakashi | 0:8fdf9a60065b | 2 | * Copyright (c) 2013 ARM Limited |
kadonotakashi | 0:8fdf9a60065b | 3 | * |
kadonotakashi | 0:8fdf9a60065b | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
kadonotakashi | 0:8fdf9a60065b | 5 | * you may not use this file except in compliance with the License. |
kadonotakashi | 0:8fdf9a60065b | 6 | * You may obtain a copy of the License at |
kadonotakashi | 0:8fdf9a60065b | 7 | * |
kadonotakashi | 0:8fdf9a60065b | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
kadonotakashi | 0:8fdf9a60065b | 9 | * |
kadonotakashi | 0:8fdf9a60065b | 10 | * Unless required by applicable law or agreed to in writing, software |
kadonotakashi | 0:8fdf9a60065b | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
kadonotakashi | 0:8fdf9a60065b | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
kadonotakashi | 0:8fdf9a60065b | 13 | * See the License for the specific language governing permissions and |
kadonotakashi | 0:8fdf9a60065b | 14 | * limitations under the License. |
kadonotakashi | 0:8fdf9a60065b | 15 | */ |
kadonotakashi | 0:8fdf9a60065b | 16 | #include <math.h> |
kadonotakashi | 0:8fdf9a60065b | 17 | #include "mbed_assert.h" |
kadonotakashi | 0:8fdf9a60065b | 18 | |
kadonotakashi | 0:8fdf9a60065b | 19 | #include "spi_api.h" |
kadonotakashi | 0:8fdf9a60065b | 20 | |
kadonotakashi | 0:8fdf9a60065b | 21 | #if DEVICE_SPI |
kadonotakashi | 0:8fdf9a60065b | 22 | |
kadonotakashi | 0:8fdf9a60065b | 23 | #include "cmsis.h" |
kadonotakashi | 0:8fdf9a60065b | 24 | #include "pinmap.h" |
kadonotakashi | 0:8fdf9a60065b | 25 | #include "mbed_error.h" |
kadonotakashi | 0:8fdf9a60065b | 26 | #include "fsl_spi.h" |
kadonotakashi | 0:8fdf9a60065b | 27 | #include "peripheral_clock_defines.h" |
kadonotakashi | 0:8fdf9a60065b | 28 | #include "PeripheralPins.h" |
kadonotakashi | 0:8fdf9a60065b | 29 | |
kadonotakashi | 0:8fdf9a60065b | 30 | /* Array of SPI peripheral base address. */ |
kadonotakashi | 0:8fdf9a60065b | 31 | static SPI_Type *const spi_address[] = SPI_BASE_PTRS; |
kadonotakashi | 0:8fdf9a60065b | 32 | /* Array of SPI bus clock frequencies */ |
kadonotakashi | 0:8fdf9a60065b | 33 | static clock_name_t const spi_clocks[] = SPI_CLOCK_FREQS; |
kadonotakashi | 0:8fdf9a60065b | 34 | |
kadonotakashi | 0:8fdf9a60065b | 35 | void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) |
kadonotakashi | 0:8fdf9a60065b | 36 | { |
kadonotakashi | 0:8fdf9a60065b | 37 | // determine the SPI to use |
kadonotakashi | 0:8fdf9a60065b | 38 | uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI); |
kadonotakashi | 0:8fdf9a60065b | 39 | uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO); |
kadonotakashi | 0:8fdf9a60065b | 40 | uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK); |
kadonotakashi | 0:8fdf9a60065b | 41 | uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL); |
kadonotakashi | 0:8fdf9a60065b | 42 | uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso); |
kadonotakashi | 0:8fdf9a60065b | 43 | uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel); |
kadonotakashi | 0:8fdf9a60065b | 44 | |
kadonotakashi | 0:8fdf9a60065b | 45 | obj->instance = pinmap_merge(spi_data, spi_cntl); |
kadonotakashi | 0:8fdf9a60065b | 46 | MBED_ASSERT((int)obj->instance != NC); |
kadonotakashi | 0:8fdf9a60065b | 47 | |
kadonotakashi | 0:8fdf9a60065b | 48 | // pin out the spi pins |
kadonotakashi | 0:8fdf9a60065b | 49 | pinmap_pinout(mosi, PinMap_SPI_MOSI); |
kadonotakashi | 0:8fdf9a60065b | 50 | pinmap_pinout(miso, PinMap_SPI_MISO); |
kadonotakashi | 0:8fdf9a60065b | 51 | pinmap_pinout(sclk, PinMap_SPI_SCLK); |
kadonotakashi | 0:8fdf9a60065b | 52 | if (ssel != NC) { |
kadonotakashi | 0:8fdf9a60065b | 53 | pinmap_pinout(ssel, PinMap_SPI_SSEL); |
kadonotakashi | 0:8fdf9a60065b | 54 | } |
kadonotakashi | 0:8fdf9a60065b | 55 | } |
kadonotakashi | 0:8fdf9a60065b | 56 | |
kadonotakashi | 0:8fdf9a60065b | 57 | void spi_free(spi_t *obj) |
kadonotakashi | 0:8fdf9a60065b | 58 | { |
kadonotakashi | 0:8fdf9a60065b | 59 | SPI_Deinit(spi_address[obj->instance]); |
kadonotakashi | 0:8fdf9a60065b | 60 | } |
kadonotakashi | 0:8fdf9a60065b | 61 | |
kadonotakashi | 0:8fdf9a60065b | 62 | void spi_format(spi_t *obj, int bits, int mode, int slave) |
kadonotakashi | 0:8fdf9a60065b | 63 | { |
kadonotakashi | 0:8fdf9a60065b | 64 | |
kadonotakashi | 0:8fdf9a60065b | 65 | spi_master_config_t master_config; |
kadonotakashi | 0:8fdf9a60065b | 66 | spi_slave_config_t slave_config; |
kadonotakashi | 0:8fdf9a60065b | 67 | |
kadonotakashi | 0:8fdf9a60065b | 68 | if ((bits != 8) && (bits != 16)) { |
kadonotakashi | 0:8fdf9a60065b | 69 | error("Only 8bits and 16bits SPI supported"); |
kadonotakashi | 0:8fdf9a60065b | 70 | return; |
kadonotakashi | 0:8fdf9a60065b | 71 | } |
kadonotakashi | 0:8fdf9a60065b | 72 | |
kadonotakashi | 0:8fdf9a60065b | 73 | if (slave) { |
kadonotakashi | 0:8fdf9a60065b | 74 | /* Slave config */ |
kadonotakashi | 0:8fdf9a60065b | 75 | SPI_SlaveGetDefaultConfig(&slave_config); |
kadonotakashi | 0:8fdf9a60065b | 76 | slave_config.dataMode = (bits == 16) ? kSPI_16BitMode : kSPI_8BitMode; |
kadonotakashi | 0:8fdf9a60065b | 77 | slave_config.polarity = (mode & 0x2) ? kSPI_ClockPolarityActiveLow : kSPI_ClockPolarityActiveHigh; |
kadonotakashi | 0:8fdf9a60065b | 78 | slave_config.phase = (mode & 0x1) ? kSPI_ClockPhaseSecondEdge : kSPI_ClockPhaseFirstEdge; |
kadonotakashi | 0:8fdf9a60065b | 79 | |
kadonotakashi | 0:8fdf9a60065b | 80 | SPI_SlaveInit(spi_address[obj->instance], &slave_config); |
kadonotakashi | 0:8fdf9a60065b | 81 | } else { |
kadonotakashi | 0:8fdf9a60065b | 82 | /* Master config */ |
kadonotakashi | 0:8fdf9a60065b | 83 | SPI_MasterGetDefaultConfig(&master_config); |
kadonotakashi | 0:8fdf9a60065b | 84 | master_config.dataMode = (bits == 16) ? kSPI_16BitMode : kSPI_8BitMode; |
kadonotakashi | 0:8fdf9a60065b | 85 | master_config.polarity = (mode & 0x2) ? kSPI_ClockPolarityActiveLow : kSPI_ClockPolarityActiveHigh; |
kadonotakashi | 0:8fdf9a60065b | 86 | master_config.phase = (mode & 0x1) ? kSPI_ClockPhaseSecondEdge : kSPI_ClockPhaseFirstEdge; |
kadonotakashi | 0:8fdf9a60065b | 87 | master_config.direction = kSPI_MsbFirst; |
kadonotakashi | 0:8fdf9a60065b | 88 | |
kadonotakashi | 0:8fdf9a60065b | 89 | SPI_MasterInit(spi_address[obj->instance], &master_config, CLOCK_GetFreq(spi_clocks[obj->instance])); |
kadonotakashi | 0:8fdf9a60065b | 90 | } |
kadonotakashi | 0:8fdf9a60065b | 91 | } |
kadonotakashi | 0:8fdf9a60065b | 92 | |
kadonotakashi | 0:8fdf9a60065b | 93 | void spi_frequency(spi_t *obj, int hz) |
kadonotakashi | 0:8fdf9a60065b | 94 | { |
kadonotakashi | 0:8fdf9a60065b | 95 | SPI_MasterSetBaudRate(spi_address[obj->instance], (uint32_t)hz, CLOCK_GetFreq(spi_clocks[obj->instance])); |
kadonotakashi | 0:8fdf9a60065b | 96 | } |
kadonotakashi | 0:8fdf9a60065b | 97 | |
kadonotakashi | 0:8fdf9a60065b | 98 | static inline int spi_readable(spi_t * obj) |
kadonotakashi | 0:8fdf9a60065b | 99 | { |
kadonotakashi | 0:8fdf9a60065b | 100 | return (SPI_GetStatusFlags(spi_address[obj->instance]) & kSPI_RxBufferFullFlag); |
kadonotakashi | 0:8fdf9a60065b | 101 | } |
kadonotakashi | 0:8fdf9a60065b | 102 | |
kadonotakashi | 0:8fdf9a60065b | 103 | int spi_master_write(spi_t *obj, int value) |
kadonotakashi | 0:8fdf9a60065b | 104 | { |
kadonotakashi | 0:8fdf9a60065b | 105 | spi_transfer_t xfer = {0}; |
kadonotakashi | 0:8fdf9a60065b | 106 | uint32_t rx_data; |
kadonotakashi | 0:8fdf9a60065b | 107 | SPI_Type *base = spi_address[obj->instance]; |
kadonotakashi | 0:8fdf9a60065b | 108 | |
kadonotakashi | 0:8fdf9a60065b | 109 | /* SPI master start transfer */ |
kadonotakashi | 0:8fdf9a60065b | 110 | xfer.txData = (uint8_t *)&value; |
kadonotakashi | 0:8fdf9a60065b | 111 | xfer.rxData = (uint8_t *)&rx_data; |
kadonotakashi | 0:8fdf9a60065b | 112 | xfer.dataSize = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U; |
kadonotakashi | 0:8fdf9a60065b | 113 | SPI_MasterTransferBlocking(base, &xfer); |
kadonotakashi | 0:8fdf9a60065b | 114 | |
kadonotakashi | 0:8fdf9a60065b | 115 | return rx_data & 0xffff; |
kadonotakashi | 0:8fdf9a60065b | 116 | } |
kadonotakashi | 0:8fdf9a60065b | 117 | |
kadonotakashi | 0:8fdf9a60065b | 118 | int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, |
kadonotakashi | 0:8fdf9a60065b | 119 | char *rx_buffer, int rx_length, char write_fill) { |
kadonotakashi | 0:8fdf9a60065b | 120 | int total = (tx_length > rx_length) ? tx_length : rx_length; |
kadonotakashi | 0:8fdf9a60065b | 121 | |
kadonotakashi | 0:8fdf9a60065b | 122 | for (int i = 0; i < total; i++) { |
kadonotakashi | 0:8fdf9a60065b | 123 | char out = (i < tx_length) ? tx_buffer[i] : write_fill; |
kadonotakashi | 0:8fdf9a60065b | 124 | char in = spi_master_write(obj, out); |
kadonotakashi | 0:8fdf9a60065b | 125 | if (i < rx_length) { |
kadonotakashi | 0:8fdf9a60065b | 126 | rx_buffer[i] = in; |
kadonotakashi | 0:8fdf9a60065b | 127 | } |
kadonotakashi | 0:8fdf9a60065b | 128 | } |
kadonotakashi | 0:8fdf9a60065b | 129 | |
kadonotakashi | 0:8fdf9a60065b | 130 | return total; |
kadonotakashi | 0:8fdf9a60065b | 131 | } |
kadonotakashi | 0:8fdf9a60065b | 132 | |
kadonotakashi | 0:8fdf9a60065b | 133 | int spi_slave_receive(spi_t *obj) |
kadonotakashi | 0:8fdf9a60065b | 134 | { |
kadonotakashi | 0:8fdf9a60065b | 135 | return spi_readable(obj); |
kadonotakashi | 0:8fdf9a60065b | 136 | } |
kadonotakashi | 0:8fdf9a60065b | 137 | |
kadonotakashi | 0:8fdf9a60065b | 138 | int spi_slave_read(spi_t *obj) |
kadonotakashi | 0:8fdf9a60065b | 139 | { |
kadonotakashi | 0:8fdf9a60065b | 140 | uint32_t rx_data; |
kadonotakashi | 0:8fdf9a60065b | 141 | |
kadonotakashi | 0:8fdf9a60065b | 142 | while (!spi_readable(obj)); |
kadonotakashi | 0:8fdf9a60065b | 143 | rx_data = SPI_ReadData(spi_address[obj->instance]); |
kadonotakashi | 0:8fdf9a60065b | 144 | |
kadonotakashi | 0:8fdf9a60065b | 145 | return rx_data & 0xffff; |
kadonotakashi | 0:8fdf9a60065b | 146 | } |
kadonotakashi | 0:8fdf9a60065b | 147 | |
kadonotakashi | 0:8fdf9a60065b | 148 | void spi_slave_write(spi_t *obj, int value) |
kadonotakashi | 0:8fdf9a60065b | 149 | { |
kadonotakashi | 0:8fdf9a60065b | 150 | SPI_Type *base = spi_address[obj->instance]; |
kadonotakashi | 0:8fdf9a60065b | 151 | size_t size = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U; |
kadonotakashi | 0:8fdf9a60065b | 152 | SPI_WriteBlocking(spi_address[obj->instance], (uint8_t *)&value, size); |
kadonotakashi | 0:8fdf9a60065b | 153 | } |
kadonotakashi | 0:8fdf9a60065b | 154 | |
kadonotakashi | 0:8fdf9a60065b | 155 | #endif |