mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_Realtek/TARGET_AMEBA/TARGET_MCU_RTL8195A/spi_api.c@189:f392fc9709a3, 2019-02-20 (annotated)
- Committer:
- AnnaBridge
- Date:
- Wed Feb 20 22:31:08 2019 +0000
- Revision:
- 189:f392fc9709a3
mbed library release version 165
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AnnaBridge | 189:f392fc9709a3 | 1 | /* mbed Microcontroller Library |
AnnaBridge | 189:f392fc9709a3 | 2 | * Copyright (c) 2013-2016 Realtek Semiconductor Corp. |
AnnaBridge | 189:f392fc9709a3 | 3 | * |
AnnaBridge | 189:f392fc9709a3 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
AnnaBridge | 189:f392fc9709a3 | 5 | * you may not use this file except in compliance with the License. |
AnnaBridge | 189:f392fc9709a3 | 6 | * You may obtain a copy of the License at |
AnnaBridge | 189:f392fc9709a3 | 7 | * |
AnnaBridge | 189:f392fc9709a3 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
AnnaBridge | 189:f392fc9709a3 | 9 | * |
AnnaBridge | 189:f392fc9709a3 | 10 | * Unless required by applicable law or agreed to in writing, software |
AnnaBridge | 189:f392fc9709a3 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
AnnaBridge | 189:f392fc9709a3 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
AnnaBridge | 189:f392fc9709a3 | 13 | * See the License for the specific language governing permissions and |
AnnaBridge | 189:f392fc9709a3 | 14 | * limitations under the License. |
AnnaBridge | 189:f392fc9709a3 | 15 | */ |
AnnaBridge | 189:f392fc9709a3 | 16 | |
AnnaBridge | 189:f392fc9709a3 | 17 | #include "objects.h" |
AnnaBridge | 189:f392fc9709a3 | 18 | #include "spi_api.h" |
AnnaBridge | 189:f392fc9709a3 | 19 | #include "spi_ex_api.h" |
AnnaBridge | 189:f392fc9709a3 | 20 | #include "PinNames.h" |
AnnaBridge | 189:f392fc9709a3 | 21 | #include "pinmap.h" |
AnnaBridge | 189:f392fc9709a3 | 22 | #include "hal_ssi.h" |
AnnaBridge | 189:f392fc9709a3 | 23 | |
AnnaBridge | 189:f392fc9709a3 | 24 | #ifdef CONFIG_MBED_ENABLED |
AnnaBridge | 189:f392fc9709a3 | 25 | #include "platform_stdlib.h" |
AnnaBridge | 189:f392fc9709a3 | 26 | #endif |
AnnaBridge | 189:f392fc9709a3 | 27 | |
AnnaBridge | 189:f392fc9709a3 | 28 | extern u32 SystemGetCpuClk(VOID); |
AnnaBridge | 189:f392fc9709a3 | 29 | extern VOID HAL_GPIO_PullCtrl(u32 pin, u32 mode); |
AnnaBridge | 189:f392fc9709a3 | 30 | |
AnnaBridge | 189:f392fc9709a3 | 31 | void spi_tx_done_callback(VOID *obj); |
AnnaBridge | 189:f392fc9709a3 | 32 | void spi_rx_done_callback(VOID *obj); |
AnnaBridge | 189:f392fc9709a3 | 33 | void spi_bus_tx_done_callback(VOID *obj); |
AnnaBridge | 189:f392fc9709a3 | 34 | |
AnnaBridge | 189:f392fc9709a3 | 35 | #ifdef CONFIG_GDMA_EN |
AnnaBridge | 189:f392fc9709a3 | 36 | HAL_GDMA_OP SpiGdmaOp; |
AnnaBridge | 189:f392fc9709a3 | 37 | #endif |
AnnaBridge | 189:f392fc9709a3 | 38 | |
AnnaBridge | 189:f392fc9709a3 | 39 | uint8_t SPI0_IS_AS_SLAVE = 0; |
AnnaBridge | 189:f392fc9709a3 | 40 | |
AnnaBridge | 189:f392fc9709a3 | 41 | //TODO: Load default Setting: It should be loaded from external setting file. |
AnnaBridge | 189:f392fc9709a3 | 42 | extern const DW_SSI_DEFAULT_SETTING SpiDefaultSetting; |
AnnaBridge | 189:f392fc9709a3 | 43 | |
AnnaBridge | 189:f392fc9709a3 | 44 | #ifdef CONFIG_MBED_ENABLED |
AnnaBridge | 189:f392fc9709a3 | 45 | #include "PeripheralPins.h" |
AnnaBridge | 189:f392fc9709a3 | 46 | #else |
AnnaBridge | 189:f392fc9709a3 | 47 | static const PinMap PinMap_SSI_MOSI[] = { |
AnnaBridge | 189:f392fc9709a3 | 48 | {PE_2, RTL_PIN_PERI(SPI0, 0, S0), RTL_PIN_FUNC(SPI0, S0)}, |
AnnaBridge | 189:f392fc9709a3 | 49 | {PC_2, RTL_PIN_PERI(SPI0, 0, S1), RTL_PIN_FUNC(SPI0, S1)}, |
AnnaBridge | 189:f392fc9709a3 | 50 | {PA_1, RTL_PIN_PERI(SPI1, 1, S0), RTL_PIN_FUNC(SPI1, S0)}, |
AnnaBridge | 189:f392fc9709a3 | 51 | {PB_6, RTL_PIN_PERI(SPI1, 1, S1), RTL_PIN_FUNC(SPI1, S1)}, |
AnnaBridge | 189:f392fc9709a3 | 52 | {PD_6, RTL_PIN_PERI(SPI1, 1, S2), RTL_PIN_FUNC(SPI1, S2)}, |
AnnaBridge | 189:f392fc9709a3 | 53 | {PG_2, RTL_PIN_PERI(SPI2, 2, S0), RTL_PIN_FUNC(SPI2, S0)}, |
AnnaBridge | 189:f392fc9709a3 | 54 | {PE_6, RTL_PIN_PERI(SPI2, 2, S1), RTL_PIN_FUNC(SPI2, S1)}, |
AnnaBridge | 189:f392fc9709a3 | 55 | {PD_2, RTL_PIN_PERI(SPI2, 2, S2), RTL_PIN_FUNC(SPI2, S2)}, |
AnnaBridge | 189:f392fc9709a3 | 56 | {NC, NC, 0} |
AnnaBridge | 189:f392fc9709a3 | 57 | }; |
AnnaBridge | 189:f392fc9709a3 | 58 | |
AnnaBridge | 189:f392fc9709a3 | 59 | static const PinMap PinMap_SSI_MISO[] = { |
AnnaBridge | 189:f392fc9709a3 | 60 | {PE_3, RTL_PIN_PERI(SPI0, 0, S0), RTL_PIN_FUNC(SPI0, S0)}, |
AnnaBridge | 189:f392fc9709a3 | 61 | {PC_3, RTL_PIN_PERI(SPI0, 0, S1), RTL_PIN_FUNC(SPI0, S1)}, |
AnnaBridge | 189:f392fc9709a3 | 62 | {PA_0, RTL_PIN_PERI(SPI1, 1, S0), RTL_PIN_FUNC(SPI1, S0)}, |
AnnaBridge | 189:f392fc9709a3 | 63 | {PB_7, RTL_PIN_PERI(SPI1, 1, S1), RTL_PIN_FUNC(SPI1, S1)}, |
AnnaBridge | 189:f392fc9709a3 | 64 | {PD_7, RTL_PIN_PERI(SPI1, 1, S2), RTL_PIN_FUNC(SPI1, S2)}, |
AnnaBridge | 189:f392fc9709a3 | 65 | {PG_3, RTL_PIN_PERI(SPI2, 2, S0), RTL_PIN_FUNC(SPI2, S0)}, |
AnnaBridge | 189:f392fc9709a3 | 66 | {PE_7, RTL_PIN_PERI(SPI2, 2, S1), RTL_PIN_FUNC(SPI2, S1)}, |
AnnaBridge | 189:f392fc9709a3 | 67 | {PD_3, RTL_PIN_PERI(SPI2, 2, S2), RTL_PIN_FUNC(SPI2, S2)}, |
AnnaBridge | 189:f392fc9709a3 | 68 | {NC, NC, 0} |
AnnaBridge | 189:f392fc9709a3 | 69 | }; |
AnnaBridge | 189:f392fc9709a3 | 70 | #endif |
AnnaBridge | 189:f392fc9709a3 | 71 | |
AnnaBridge | 189:f392fc9709a3 | 72 | void spi_init (spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) |
AnnaBridge | 189:f392fc9709a3 | 73 | { |
AnnaBridge | 189:f392fc9709a3 | 74 | SSI_DBG_ENTRANCE("spi_init()\n"); |
AnnaBridge | 189:f392fc9709a3 | 75 | |
AnnaBridge | 189:f392fc9709a3 | 76 | int ssi_mosi, ssi_miso, ssi_peri; |
AnnaBridge | 189:f392fc9709a3 | 77 | uint8_t ssi_idx, ssi_pinmux; |
AnnaBridge | 189:f392fc9709a3 | 78 | PHAL_SSI_ADAPTOR pHalSsiAdaptor; |
AnnaBridge | 189:f392fc9709a3 | 79 | PHAL_SSI_OP pHalSsiOp; |
AnnaBridge | 189:f392fc9709a3 | 80 | |
AnnaBridge | 189:f392fc9709a3 | 81 | _memset((void*)obj, 0, sizeof(spi_t)); |
AnnaBridge | 189:f392fc9709a3 | 82 | obj->state = 0; |
AnnaBridge | 189:f392fc9709a3 | 83 | |
AnnaBridge | 189:f392fc9709a3 | 84 | uint32_t SystemClock = SystemGetCpuClk(); |
AnnaBridge | 189:f392fc9709a3 | 85 | uint32_t MaxSsiFreq = (SystemClock >> 2) >> 1; |
AnnaBridge | 189:f392fc9709a3 | 86 | |
AnnaBridge | 189:f392fc9709a3 | 87 | /* SsiClockDivider doesn't support odd number */ |
AnnaBridge | 189:f392fc9709a3 | 88 | DBG_SSI_INFO("SystemClock: %d\n", SystemClock); |
AnnaBridge | 189:f392fc9709a3 | 89 | DBG_SSI_INFO("MaxSsiFreq : %d\n", MaxSsiFreq); |
AnnaBridge | 189:f392fc9709a3 | 90 | |
AnnaBridge | 189:f392fc9709a3 | 91 | ssi_mosi = pinmap_peripheral(mosi, PinMap_SSI_MOSI); |
AnnaBridge | 189:f392fc9709a3 | 92 | ssi_miso = pinmap_peripheral(miso, PinMap_SSI_MISO); |
AnnaBridge | 189:f392fc9709a3 | 93 | |
AnnaBridge | 189:f392fc9709a3 | 94 | ssi_peri = pinmap_merge(ssi_mosi, ssi_miso); |
AnnaBridge | 189:f392fc9709a3 | 95 | if (unlikely(ssi_peri == NC)) { |
AnnaBridge | 189:f392fc9709a3 | 96 | DBG_SSI_ERR("spi_init(): Cannot find matched SSI index.\n"); |
AnnaBridge | 189:f392fc9709a3 | 97 | return; |
AnnaBridge | 189:f392fc9709a3 | 98 | } |
AnnaBridge | 189:f392fc9709a3 | 99 | obj->sclk = (u8)sclk; |
AnnaBridge | 189:f392fc9709a3 | 100 | ssi_idx = RTL_GET_PERI_IDX(ssi_peri); |
AnnaBridge | 189:f392fc9709a3 | 101 | ssi_pinmux = RTL_GET_PERI_SEL(ssi_peri); |
AnnaBridge | 189:f392fc9709a3 | 102 | DBG_SSI_INFO("ssi_peri: %d, ssi_idx: %d, ssi_pinmux: %d\n", ssi_peri, ssi_idx, ssi_pinmux); |
AnnaBridge | 189:f392fc9709a3 | 103 | |
AnnaBridge | 189:f392fc9709a3 | 104 | pHalSsiAdaptor = &obj->spi_adp; |
AnnaBridge | 189:f392fc9709a3 | 105 | pHalSsiOp = &obj->spi_op; |
AnnaBridge | 189:f392fc9709a3 | 106 | |
AnnaBridge | 189:f392fc9709a3 | 107 | pHalSsiAdaptor->Index = ssi_idx; |
AnnaBridge | 189:f392fc9709a3 | 108 | pHalSsiAdaptor->PinmuxSelect = ssi_pinmux; |
AnnaBridge | 189:f392fc9709a3 | 109 | pHalSsiAdaptor->Role = SSI_MASTER; |
AnnaBridge | 189:f392fc9709a3 | 110 | |
AnnaBridge | 189:f392fc9709a3 | 111 | HalSsiOpInit((VOID*)pHalSsiOp); |
AnnaBridge | 189:f392fc9709a3 | 112 | |
AnnaBridge | 189:f392fc9709a3 | 113 | pHalSsiOp->HalSsiSetDeviceRole(pHalSsiAdaptor, pHalSsiAdaptor->Role); |
AnnaBridge | 189:f392fc9709a3 | 114 | |
AnnaBridge | 189:f392fc9709a3 | 115 | /* Pinmux workaround */ |
AnnaBridge | 189:f392fc9709a3 | 116 | if ((ssi_idx == 0) && (ssi_pinmux == SSI0_MUX_TO_GPIOC)) { |
AnnaBridge | 189:f392fc9709a3 | 117 | EEPROM_PIN_CTRL(OFF); |
AnnaBridge | 189:f392fc9709a3 | 118 | } |
AnnaBridge | 189:f392fc9709a3 | 119 | |
AnnaBridge | 189:f392fc9709a3 | 120 | if ((ssi_idx == 0) && (ssi_pinmux == SSI0_MUX_TO_GPIOE)) { |
AnnaBridge | 189:f392fc9709a3 | 121 | DBG_SSI_WARN(ANSI_COLOR_MAGENTA"SPI0 Pin may conflict with JTAG\r\n"ANSI_COLOR_RESET); |
AnnaBridge | 189:f392fc9709a3 | 122 | } |
AnnaBridge | 189:f392fc9709a3 | 123 | |
AnnaBridge | 189:f392fc9709a3 | 124 | //TODO: Implement default setting structure. |
AnnaBridge | 189:f392fc9709a3 | 125 | pHalSsiOp->HalSsiLoadSetting(pHalSsiAdaptor, (void*)&SpiDefaultSetting); |
AnnaBridge | 189:f392fc9709a3 | 126 | pHalSsiAdaptor->DefaultRxThresholdLevel = SpiDefaultSetting.RxThresholdLevel; |
AnnaBridge | 189:f392fc9709a3 | 127 | |
AnnaBridge | 189:f392fc9709a3 | 128 | if(HalSsiInit(pHalSsiAdaptor) != HAL_OK){ |
AnnaBridge | 189:f392fc9709a3 | 129 | DBG_SSI_ERR(ANSI_COLOR_RED"spi_init(): SPI %x init fails.\n"ANSI_COLOR_RESET,pHalSsiAdaptor->Index); |
AnnaBridge | 189:f392fc9709a3 | 130 | return; |
AnnaBridge | 189:f392fc9709a3 | 131 | } |
AnnaBridge | 189:f392fc9709a3 | 132 | |
AnnaBridge | 189:f392fc9709a3 | 133 | pHalSsiAdaptor->TxCompCallback = spi_tx_done_callback; |
AnnaBridge | 189:f392fc9709a3 | 134 | pHalSsiAdaptor->TxCompCbPara = (void*)obj; |
AnnaBridge | 189:f392fc9709a3 | 135 | pHalSsiAdaptor->RxCompCallback = spi_rx_done_callback; |
AnnaBridge | 189:f392fc9709a3 | 136 | pHalSsiAdaptor->RxCompCbPara = (void*)obj; |
AnnaBridge | 189:f392fc9709a3 | 137 | pHalSsiAdaptor->TxIdleCallback = spi_bus_tx_done_callback; |
AnnaBridge | 189:f392fc9709a3 | 138 | pHalSsiAdaptor->TxIdleCbPara = (void*)obj; |
AnnaBridge | 189:f392fc9709a3 | 139 | |
AnnaBridge | 189:f392fc9709a3 | 140 | #ifdef CONFIG_GDMA_EN |
AnnaBridge | 189:f392fc9709a3 | 141 | HalGdmaOpInit((VOID*)&SpiGdmaOp); |
AnnaBridge | 189:f392fc9709a3 | 142 | pHalSsiAdaptor->DmaConfig.pHalGdmaOp = &SpiGdmaOp; |
AnnaBridge | 189:f392fc9709a3 | 143 | pHalSsiAdaptor->DmaConfig.pRxHalGdmaAdapter = &obj->spi_gdma_adp_rx; |
AnnaBridge | 189:f392fc9709a3 | 144 | pHalSsiAdaptor->DmaConfig.pTxHalGdmaAdapter = &obj->spi_gdma_adp_tx; |
AnnaBridge | 189:f392fc9709a3 | 145 | obj->dma_en = 0; |
AnnaBridge | 189:f392fc9709a3 | 146 | pHalSsiAdaptor->HaveTxChannel = 0; |
AnnaBridge | 189:f392fc9709a3 | 147 | pHalSsiAdaptor->HaveRxChannel = 0; |
AnnaBridge | 189:f392fc9709a3 | 148 | #endif |
AnnaBridge | 189:f392fc9709a3 | 149 | } |
AnnaBridge | 189:f392fc9709a3 | 150 | |
AnnaBridge | 189:f392fc9709a3 | 151 | void spi_free (spi_t *obj) |
AnnaBridge | 189:f392fc9709a3 | 152 | { |
AnnaBridge | 189:f392fc9709a3 | 153 | PHAL_SSI_ADAPTOR pHalSsiAdaptor; |
AnnaBridge | 189:f392fc9709a3 | 154 | pHalSsiAdaptor = &obj->spi_adp; |
AnnaBridge | 189:f392fc9709a3 | 155 | HalSsiDeInit(pHalSsiAdaptor); |
AnnaBridge | 189:f392fc9709a3 | 156 | |
AnnaBridge | 189:f392fc9709a3 | 157 | SPI0_MULTI_CS_CTRL(OFF); |
AnnaBridge | 189:f392fc9709a3 | 158 | |
AnnaBridge | 189:f392fc9709a3 | 159 | #ifdef CONFIG_GDMA_EN |
AnnaBridge | 189:f392fc9709a3 | 160 | if (obj->dma_en & SPI_DMA_RX_EN) { |
AnnaBridge | 189:f392fc9709a3 | 161 | HalSsiRxGdmaDeInit(pHalSsiAdaptor); |
AnnaBridge | 189:f392fc9709a3 | 162 | } |
AnnaBridge | 189:f392fc9709a3 | 163 | |
AnnaBridge | 189:f392fc9709a3 | 164 | if (obj->dma_en & SPI_DMA_TX_EN) { |
AnnaBridge | 189:f392fc9709a3 | 165 | HalSsiTxGdmaDeInit(pHalSsiAdaptor); |
AnnaBridge | 189:f392fc9709a3 | 166 | } |
AnnaBridge | 189:f392fc9709a3 | 167 | obj->dma_en = 0; |
AnnaBridge | 189:f392fc9709a3 | 168 | #endif |
AnnaBridge | 189:f392fc9709a3 | 169 | } |
AnnaBridge | 189:f392fc9709a3 | 170 | |
AnnaBridge | 189:f392fc9709a3 | 171 | void spi_format (spi_t *obj, int bits, int mode, int slave) |
AnnaBridge | 189:f392fc9709a3 | 172 | { |
AnnaBridge | 189:f392fc9709a3 | 173 | PHAL_SSI_ADAPTOR pHalSsiAdaptor; |
AnnaBridge | 189:f392fc9709a3 | 174 | PHAL_SSI_OP pHalSsiOp; |
AnnaBridge | 189:f392fc9709a3 | 175 | |
AnnaBridge | 189:f392fc9709a3 | 176 | pHalSsiAdaptor = &obj->spi_adp; |
AnnaBridge | 189:f392fc9709a3 | 177 | pHalSsiOp = &obj->spi_op; |
AnnaBridge | 189:f392fc9709a3 | 178 | |
AnnaBridge | 189:f392fc9709a3 | 179 | pHalSsiAdaptor->DataFrameSize = (bits - 1); |
AnnaBridge | 189:f392fc9709a3 | 180 | |
AnnaBridge | 189:f392fc9709a3 | 181 | /* |
AnnaBridge | 189:f392fc9709a3 | 182 | * mode | POL PHA |
AnnaBridge | 189:f392fc9709a3 | 183 | * -----+-------- |
AnnaBridge | 189:f392fc9709a3 | 184 | * 0 | 0 0 |
AnnaBridge | 189:f392fc9709a3 | 185 | * 1 | 0 1 |
AnnaBridge | 189:f392fc9709a3 | 186 | * 2 | 1 0 |
AnnaBridge | 189:f392fc9709a3 | 187 | * 3 | 1 1 |
AnnaBridge | 189:f392fc9709a3 | 188 | * |
AnnaBridge | 189:f392fc9709a3 | 189 | * SCPOL_INACTIVE_IS_LOW = 0, |
AnnaBridge | 189:f392fc9709a3 | 190 | * SCPOL_INACTIVE_IS_HIGH = 1 |
AnnaBridge | 189:f392fc9709a3 | 191 | * |
AnnaBridge | 189:f392fc9709a3 | 192 | * SCPH_TOGGLES_IN_MIDDLE = 0, |
AnnaBridge | 189:f392fc9709a3 | 193 | * SCPH_TOGGLES_AT_START = 1 |
AnnaBridge | 189:f392fc9709a3 | 194 | */ |
AnnaBridge | 189:f392fc9709a3 | 195 | switch (mode) |
AnnaBridge | 189:f392fc9709a3 | 196 | { |
AnnaBridge | 189:f392fc9709a3 | 197 | case 0: |
AnnaBridge | 189:f392fc9709a3 | 198 | pHalSsiAdaptor->SclkPolarity = SCPOL_INACTIVE_IS_LOW; |
AnnaBridge | 189:f392fc9709a3 | 199 | pHalSsiAdaptor->SclkPhase = SCPH_TOGGLES_IN_MIDDLE; |
AnnaBridge | 189:f392fc9709a3 | 200 | break; |
AnnaBridge | 189:f392fc9709a3 | 201 | case 1: |
AnnaBridge | 189:f392fc9709a3 | 202 | pHalSsiAdaptor->SclkPolarity = SCPOL_INACTIVE_IS_LOW; |
AnnaBridge | 189:f392fc9709a3 | 203 | pHalSsiAdaptor->SclkPhase = SCPH_TOGGLES_AT_START; |
AnnaBridge | 189:f392fc9709a3 | 204 | break; |
AnnaBridge | 189:f392fc9709a3 | 205 | case 2: |
AnnaBridge | 189:f392fc9709a3 | 206 | pHalSsiAdaptor->SclkPolarity = SCPOL_INACTIVE_IS_HIGH; |
AnnaBridge | 189:f392fc9709a3 | 207 | pHalSsiAdaptor->SclkPhase = SCPH_TOGGLES_IN_MIDDLE; |
AnnaBridge | 189:f392fc9709a3 | 208 | break; |
AnnaBridge | 189:f392fc9709a3 | 209 | case 3: |
AnnaBridge | 189:f392fc9709a3 | 210 | pHalSsiAdaptor->SclkPolarity = SCPOL_INACTIVE_IS_HIGH; |
AnnaBridge | 189:f392fc9709a3 | 211 | pHalSsiAdaptor->SclkPhase = SCPH_TOGGLES_AT_START; |
AnnaBridge | 189:f392fc9709a3 | 212 | break; |
AnnaBridge | 189:f392fc9709a3 | 213 | default: // same as 3 |
AnnaBridge | 189:f392fc9709a3 | 214 | pHalSsiAdaptor->SclkPolarity = SCPOL_INACTIVE_IS_HIGH; |
AnnaBridge | 189:f392fc9709a3 | 215 | pHalSsiAdaptor->SclkPhase = SCPH_TOGGLES_AT_START; |
AnnaBridge | 189:f392fc9709a3 | 216 | break; |
AnnaBridge | 189:f392fc9709a3 | 217 | } |
AnnaBridge | 189:f392fc9709a3 | 218 | |
AnnaBridge | 189:f392fc9709a3 | 219 | if (slave == 1) { |
AnnaBridge | 189:f392fc9709a3 | 220 | if (pHalSsiAdaptor->Index == 0) { |
AnnaBridge | 189:f392fc9709a3 | 221 | pHalSsiAdaptor->Role = SSI_SLAVE; |
AnnaBridge | 189:f392fc9709a3 | 222 | pHalSsiAdaptor->SlaveOutputEnable = SLV_TXD_ENABLE; // <-- Slave only |
AnnaBridge | 189:f392fc9709a3 | 223 | SPI0_IS_AS_SLAVE = 1; |
AnnaBridge | 189:f392fc9709a3 | 224 | DBG_SSI_INFO("SPI0 is as slave\n"); |
AnnaBridge | 189:f392fc9709a3 | 225 | } else { |
AnnaBridge | 189:f392fc9709a3 | 226 | DBG_SSI_ERR("The SPI%d cannot work as Slave mode, only SPI0 does.\r\n", pHalSsiAdaptor->Index); |
AnnaBridge | 189:f392fc9709a3 | 227 | pHalSsiAdaptor->Role = SSI_MASTER; |
AnnaBridge | 189:f392fc9709a3 | 228 | } |
AnnaBridge | 189:f392fc9709a3 | 229 | } else { |
AnnaBridge | 189:f392fc9709a3 | 230 | pHalSsiAdaptor->Role = SSI_MASTER; |
AnnaBridge | 189:f392fc9709a3 | 231 | } |
AnnaBridge | 189:f392fc9709a3 | 232 | pHalSsiOp->HalSsiSetDeviceRole(pHalSsiAdaptor, pHalSsiAdaptor->Role); |
AnnaBridge | 189:f392fc9709a3 | 233 | |
AnnaBridge | 189:f392fc9709a3 | 234 | #ifdef CONFIG_GPIO_EN |
AnnaBridge | 189:f392fc9709a3 | 235 | if (pHalSsiAdaptor->Role == SSI_SLAVE) { |
AnnaBridge | 189:f392fc9709a3 | 236 | if (pHalSsiAdaptor->SclkPolarity == SCPOL_INACTIVE_IS_LOW) { |
AnnaBridge | 189:f392fc9709a3 | 237 | HAL_GPIO_PullCtrl((u32)obj->sclk, hal_PullDown); |
AnnaBridge | 189:f392fc9709a3 | 238 | } else { |
AnnaBridge | 189:f392fc9709a3 | 239 | HAL_GPIO_PullCtrl((u32)obj->sclk, hal_PullUp); |
AnnaBridge | 189:f392fc9709a3 | 240 | } |
AnnaBridge | 189:f392fc9709a3 | 241 | } |
AnnaBridge | 189:f392fc9709a3 | 242 | #endif |
AnnaBridge | 189:f392fc9709a3 | 243 | HalSsiSetFormat(pHalSsiAdaptor); |
AnnaBridge | 189:f392fc9709a3 | 244 | } |
AnnaBridge | 189:f392fc9709a3 | 245 | |
AnnaBridge | 189:f392fc9709a3 | 246 | void spi_frequency (spi_t *obj, int hz) |
AnnaBridge | 189:f392fc9709a3 | 247 | { |
AnnaBridge | 189:f392fc9709a3 | 248 | PHAL_SSI_ADAPTOR pHalSsiAdaptor; |
AnnaBridge | 189:f392fc9709a3 | 249 | |
AnnaBridge | 189:f392fc9709a3 | 250 | pHalSsiAdaptor = &obj->spi_adp; |
AnnaBridge | 189:f392fc9709a3 | 251 | HalSsiSetSclk(pHalSsiAdaptor, (u32)hz); |
AnnaBridge | 189:f392fc9709a3 | 252 | } |
AnnaBridge | 189:f392fc9709a3 | 253 | |
AnnaBridge | 189:f392fc9709a3 | 254 | static inline void ssi_write (spi_t *obj, int value) |
AnnaBridge | 189:f392fc9709a3 | 255 | { |
AnnaBridge | 189:f392fc9709a3 | 256 | PHAL_SSI_ADAPTOR pHalSsiAdaptor; |
AnnaBridge | 189:f392fc9709a3 | 257 | PHAL_SSI_OP pHalSsiOp; |
AnnaBridge | 189:f392fc9709a3 | 258 | |
AnnaBridge | 189:f392fc9709a3 | 259 | pHalSsiAdaptor = &obj->spi_adp; |
AnnaBridge | 189:f392fc9709a3 | 260 | pHalSsiOp = &obj->spi_op; |
AnnaBridge | 189:f392fc9709a3 | 261 | |
AnnaBridge | 189:f392fc9709a3 | 262 | while (!pHalSsiOp->HalSsiWriteable(pHalSsiAdaptor)); |
AnnaBridge | 189:f392fc9709a3 | 263 | pHalSsiOp->HalSsiWrite((VOID*)pHalSsiAdaptor, value); |
AnnaBridge | 189:f392fc9709a3 | 264 | } |
AnnaBridge | 189:f392fc9709a3 | 265 | |
AnnaBridge | 189:f392fc9709a3 | 266 | static inline int ssi_read(spi_t *obj) |
AnnaBridge | 189:f392fc9709a3 | 267 | { |
AnnaBridge | 189:f392fc9709a3 | 268 | PHAL_SSI_ADAPTOR pHalSsiAdaptor; |
AnnaBridge | 189:f392fc9709a3 | 269 | PHAL_SSI_OP pHalSsiOp; |
AnnaBridge | 189:f392fc9709a3 | 270 | |
AnnaBridge | 189:f392fc9709a3 | 271 | pHalSsiAdaptor = &obj->spi_adp; |
AnnaBridge | 189:f392fc9709a3 | 272 | pHalSsiOp = &obj->spi_op; |
AnnaBridge | 189:f392fc9709a3 | 273 | |
AnnaBridge | 189:f392fc9709a3 | 274 | while (!pHalSsiOp->HalSsiReadable(pHalSsiAdaptor)); |
AnnaBridge | 189:f392fc9709a3 | 275 | return (int)pHalSsiOp->HalSsiRead(pHalSsiAdaptor); |
AnnaBridge | 189:f392fc9709a3 | 276 | } |
AnnaBridge | 189:f392fc9709a3 | 277 | |
AnnaBridge | 189:f392fc9709a3 | 278 | int spi_master_write (spi_t *obj, int value) |
AnnaBridge | 189:f392fc9709a3 | 279 | { |
AnnaBridge | 189:f392fc9709a3 | 280 | ssi_write(obj, value); |
AnnaBridge | 189:f392fc9709a3 | 281 | return ssi_read(obj); |
AnnaBridge | 189:f392fc9709a3 | 282 | } |
AnnaBridge | 189:f392fc9709a3 | 283 | |
AnnaBridge | 189:f392fc9709a3 | 284 | int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, |
AnnaBridge | 189:f392fc9709a3 | 285 | char *rx_buffer, int rx_length, char write_fill) |
AnnaBridge | 189:f392fc9709a3 | 286 | { |
AnnaBridge | 189:f392fc9709a3 | 287 | int total = (tx_length > rx_length) ? tx_length : rx_length; |
AnnaBridge | 189:f392fc9709a3 | 288 | int i; |
AnnaBridge | 189:f392fc9709a3 | 289 | char out, in; |
AnnaBridge | 189:f392fc9709a3 | 290 | |
AnnaBridge | 189:f392fc9709a3 | 291 | for (i = 0; i < total; i++) { |
AnnaBridge | 189:f392fc9709a3 | 292 | out = (i < tx_length) ? tx_buffer[i] : write_fill; |
AnnaBridge | 189:f392fc9709a3 | 293 | in = spi_master_write(obj, out); |
AnnaBridge | 189:f392fc9709a3 | 294 | if (i < rx_length) { |
AnnaBridge | 189:f392fc9709a3 | 295 | rx_buffer[i] = in; |
AnnaBridge | 189:f392fc9709a3 | 296 | } |
AnnaBridge | 189:f392fc9709a3 | 297 | } |
AnnaBridge | 189:f392fc9709a3 | 298 | |
AnnaBridge | 189:f392fc9709a3 | 299 | return total; |
AnnaBridge | 189:f392fc9709a3 | 300 | } |
AnnaBridge | 189:f392fc9709a3 | 301 | |
AnnaBridge | 189:f392fc9709a3 | 302 | int spi_slave_receive (spi_t *obj) |
AnnaBridge | 189:f392fc9709a3 | 303 | { |
AnnaBridge | 189:f392fc9709a3 | 304 | PHAL_SSI_ADAPTOR pHalSsiAdaptor; |
AnnaBridge | 189:f392fc9709a3 | 305 | PHAL_SSI_OP pHalSsiOp; |
AnnaBridge | 189:f392fc9709a3 | 306 | int Readable; |
AnnaBridge | 189:f392fc9709a3 | 307 | int Busy; |
AnnaBridge | 189:f392fc9709a3 | 308 | |
AnnaBridge | 189:f392fc9709a3 | 309 | pHalSsiAdaptor = &obj->spi_adp; |
AnnaBridge | 189:f392fc9709a3 | 310 | pHalSsiOp = &obj->spi_op; |
AnnaBridge | 189:f392fc9709a3 | 311 | |
AnnaBridge | 189:f392fc9709a3 | 312 | Readable = pHalSsiOp->HalSsiReadable(pHalSsiAdaptor); |
AnnaBridge | 189:f392fc9709a3 | 313 | Busy = (int)pHalSsiOp->HalSsiBusy(pHalSsiAdaptor); |
AnnaBridge | 189:f392fc9709a3 | 314 | return ((Readable && !Busy) ? 1 : 0); |
AnnaBridge | 189:f392fc9709a3 | 315 | } |
AnnaBridge | 189:f392fc9709a3 | 316 | |
AnnaBridge | 189:f392fc9709a3 | 317 | int spi_slave_read (spi_t *obj) |
AnnaBridge | 189:f392fc9709a3 | 318 | { |
AnnaBridge | 189:f392fc9709a3 | 319 | return ssi_read(obj); |
AnnaBridge | 189:f392fc9709a3 | 320 | } |
AnnaBridge | 189:f392fc9709a3 | 321 | |
AnnaBridge | 189:f392fc9709a3 | 322 | void spi_slave_write (spi_t *obj, int value) |
AnnaBridge | 189:f392fc9709a3 | 323 | { |
AnnaBridge | 189:f392fc9709a3 | 324 | ssi_write(obj, value); |
AnnaBridge | 189:f392fc9709a3 | 325 | } |
AnnaBridge | 189:f392fc9709a3 | 326 | |
AnnaBridge | 189:f392fc9709a3 | 327 | int spi_busy (spi_t *obj) |
AnnaBridge | 189:f392fc9709a3 | 328 | { |
AnnaBridge | 189:f392fc9709a3 | 329 | PHAL_SSI_ADAPTOR pHalSsiAdaptor; |
AnnaBridge | 189:f392fc9709a3 | 330 | PHAL_SSI_OP pHalSsiOp; |
AnnaBridge | 189:f392fc9709a3 | 331 | |
AnnaBridge | 189:f392fc9709a3 | 332 | pHalSsiAdaptor = &obj->spi_adp; |
AnnaBridge | 189:f392fc9709a3 | 333 | pHalSsiOp = &obj->spi_op; |
AnnaBridge | 189:f392fc9709a3 | 334 | |
AnnaBridge | 189:f392fc9709a3 | 335 | return (int)pHalSsiOp->HalSsiBusy(pHalSsiAdaptor); |
AnnaBridge | 189:f392fc9709a3 | 336 | } |
AnnaBridge | 189:f392fc9709a3 | 337 | |
AnnaBridge | 189:f392fc9709a3 | 338 | // Bus Idle: Real TX done, TX FIFO empty and bus shift all data out already |
AnnaBridge | 189:f392fc9709a3 | 339 | void spi_bus_tx_done_callback(VOID *obj) |
AnnaBridge | 189:f392fc9709a3 | 340 | { |
AnnaBridge | 189:f392fc9709a3 | 341 | spi_t *spi_obj = (spi_t *)obj; |
AnnaBridge | 189:f392fc9709a3 | 342 | spi_irq_handler handler; |
AnnaBridge | 189:f392fc9709a3 | 343 | |
AnnaBridge | 189:f392fc9709a3 | 344 | if (spi_obj->bus_tx_done_handler) { |
AnnaBridge | 189:f392fc9709a3 | 345 | handler = (spi_irq_handler)spi_obj->bus_tx_done_handler; |
AnnaBridge | 189:f392fc9709a3 | 346 | handler(spi_obj->bus_tx_done_irq_id, (SpiIrq)0); |
AnnaBridge | 189:f392fc9709a3 | 347 | } |
AnnaBridge | 189:f392fc9709a3 | 348 | } |
AnnaBridge | 189:f392fc9709a3 | 349 | |
AnnaBridge | 189:f392fc9709a3 | 350 | void spi_tx_done_callback(VOID *obj) |
AnnaBridge | 189:f392fc9709a3 | 351 | { |
AnnaBridge | 189:f392fc9709a3 | 352 | spi_t *spi_obj = (spi_t *)obj; |
AnnaBridge | 189:f392fc9709a3 | 353 | spi_irq_handler handler; |
AnnaBridge | 189:f392fc9709a3 | 354 | |
AnnaBridge | 189:f392fc9709a3 | 355 | if (spi_obj->state & SPI_STATE_TX_BUSY) { |
AnnaBridge | 189:f392fc9709a3 | 356 | spi_obj->state &= ~SPI_STATE_TX_BUSY; |
AnnaBridge | 189:f392fc9709a3 | 357 | if (spi_obj->irq_handler) { |
AnnaBridge | 189:f392fc9709a3 | 358 | handler = (spi_irq_handler)spi_obj->irq_handler; |
AnnaBridge | 189:f392fc9709a3 | 359 | handler(spi_obj->irq_id, SpiTxIrq); |
AnnaBridge | 189:f392fc9709a3 | 360 | } |
AnnaBridge | 189:f392fc9709a3 | 361 | } |
AnnaBridge | 189:f392fc9709a3 | 362 | } |
AnnaBridge | 189:f392fc9709a3 | 363 | |
AnnaBridge | 189:f392fc9709a3 | 364 | void spi_rx_done_callback(VOID *obj) |
AnnaBridge | 189:f392fc9709a3 | 365 | { |
AnnaBridge | 189:f392fc9709a3 | 366 | spi_t *spi_obj = (spi_t *)obj; |
AnnaBridge | 189:f392fc9709a3 | 367 | spi_irq_handler handler; |
AnnaBridge | 189:f392fc9709a3 | 368 | |
AnnaBridge | 189:f392fc9709a3 | 369 | spi_obj->state &= ~SPI_STATE_RX_BUSY; |
AnnaBridge | 189:f392fc9709a3 | 370 | if (spi_obj->irq_handler) { |
AnnaBridge | 189:f392fc9709a3 | 371 | handler = (spi_irq_handler)spi_obj->irq_handler; |
AnnaBridge | 189:f392fc9709a3 | 372 | handler(spi_obj->irq_id, SpiRxIrq); |
AnnaBridge | 189:f392fc9709a3 | 373 | } |
AnnaBridge | 189:f392fc9709a3 | 374 | } |
AnnaBridge | 189:f392fc9709a3 | 375 |