mbed-os
Fork of mbed-os by
targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_spi.c@0:f269e3021894, 2016-10-23 (annotated)
- Committer:
- elessair
- Date:
- Sun Oct 23 15:10:02 2016 +0000
- Revision:
- 0:f269e3021894
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
elessair | 0:f269e3021894 | 1 | /** |
elessair | 0:f269e3021894 | 2 | ****************************************************************************** |
elessair | 0:f269e3021894 | 3 | * @file spi.c |
elessair | 0:f269e3021894 | 4 | * @brief Implementation of a IPC 7207 SPI master driver |
elessair | 0:f269e3021894 | 5 | * @internal |
elessair | 0:f269e3021894 | 6 | * @author ON Semiconductor |
elessair | 0:f269e3021894 | 7 | * @version $Rev: $ |
elessair | 0:f269e3021894 | 8 | * @date $Date: 2016-02-05 $ |
elessair | 0:f269e3021894 | 9 | ****************************************************************************** |
elessair | 0:f269e3021894 | 10 | * Copyright 2016 Semiconductor Components Industries LLC (d/b/a ON Semiconductor). |
elessair | 0:f269e3021894 | 11 | * All rights reserved. This software and/or documentation is licensed by ON Semiconductor |
elessair | 0:f269e3021894 | 12 | * under limited terms and conditions. The terms and conditions pertaining to the software |
elessair | 0:f269e3021894 | 13 | * and/or documentation are available at http://www.onsemi.com/site/pdf/ONSEMI_T&C.pdf |
elessair | 0:f269e3021894 | 14 | * (ON Semiconductor Standard Terms and Conditions of Sale, Section 8 Software) and |
elessair | 0:f269e3021894 | 15 | * if applicable the software license agreement. Do not use this software and/or |
elessair | 0:f269e3021894 | 16 | * documentation unless you have carefully read and you agree to the limited terms and |
elessair | 0:f269e3021894 | 17 | * conditions. By using this software and/or documentation, you agree to the limited |
elessair | 0:f269e3021894 | 18 | * terms and conditions. |
elessair | 0:f269e3021894 | 19 | * |
elessair | 0:f269e3021894 | 20 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED |
elessair | 0:f269e3021894 | 21 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF |
elessair | 0:f269e3021894 | 22 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. |
elessair | 0:f269e3021894 | 23 | * ON SEMICONDUCTOR SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, |
elessair | 0:f269e3021894 | 24 | * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. |
elessair | 0:f269e3021894 | 25 | * @endinternal |
elessair | 0:f269e3021894 | 26 | * |
elessair | 0:f269e3021894 | 27 | * @ingroup spi |
elessair | 0:f269e3021894 | 28 | * |
elessair | 0:f269e3021894 | 29 | * @details |
elessair | 0:f269e3021894 | 30 | * |
elessair | 0:f269e3021894 | 31 | */ |
elessair | 0:f269e3021894 | 32 | #if DEVICE_SPI |
elessair | 0:f269e3021894 | 33 | |
elessair | 0:f269e3021894 | 34 | #include "spi.h" |
elessair | 0:f269e3021894 | 35 | #include "clock.h" |
elessair | 0:f269e3021894 | 36 | #include "objects.h" |
elessair | 0:f269e3021894 | 37 | #include "spi_api.h" |
elessair | 0:f269e3021894 | 38 | #include "PeripheralPins.h" |
elessair | 0:f269e3021894 | 39 | #include "spi_ipc7207_map.h" |
elessair | 0:f269e3021894 | 40 | #include "crossbar.h" |
elessair | 0:f269e3021894 | 41 | #include "pad.h" |
elessair | 0:f269e3021894 | 42 | #include "mbed_assert.h" |
elessair | 0:f269e3021894 | 43 | |
elessair | 0:f269e3021894 | 44 | /** Initializes a spi device. |
elessair | 0:f269e3021894 | 45 | * @details |
elessair | 0:f269e3021894 | 46 | * |
elessair | 0:f269e3021894 | 47 | * @param obj A spi device instance. |
elessair | 0:f269e3021894 | 48 | * @param mosi pin to used as SPI MOSI |
elessair | 0:f269e3021894 | 49 | * @param miso pin to used as SPI MISO |
elessair | 0:f269e3021894 | 50 | * @param sclk pin to used as SPI SCLK |
elessair | 0:f269e3021894 | 51 | * @return None |
elessair | 0:f269e3021894 | 52 | */ |
elessair | 0:f269e3021894 | 53 | void fSpiInit(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) |
elessair | 0:f269e3021894 | 54 | { |
elessair | 0:f269e3021894 | 55 | uint32_t clockDivisor; |
elessair | 0:f269e3021894 | 56 | |
elessair | 0:f269e3021894 | 57 | /* determine the SPI to use */ |
elessair | 0:f269e3021894 | 58 | SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); |
elessair | 0:f269e3021894 | 59 | SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); |
elessair | 0:f269e3021894 | 60 | SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); |
elessair | 0:f269e3021894 | 61 | SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); |
elessair | 0:f269e3021894 | 62 | |
elessair | 0:f269e3021894 | 63 | SPIName spi_data_1 = (SPIName)pinmap_merge(spi_mosi, spi_miso); |
elessair | 0:f269e3021894 | 64 | SPIName spi_data_2 = (SPIName)pinmap_merge(spi_sclk, spi_ssel); |
elessair | 0:f269e3021894 | 65 | |
elessair | 0:f269e3021894 | 66 | obj->membase = (SpiIpc7207Reg_pt)pinmap_merge(spi_data_1, spi_data_2); |
elessair | 0:f269e3021894 | 67 | MBED_ASSERT((int)obj->membase != NC); |
elessair | 0:f269e3021894 | 68 | |
elessair | 0:f269e3021894 | 69 | /* Check device to be activated */ |
elessair | 0:f269e3021894 | 70 | if(obj->membase == SPI1REG) { |
elessair | 0:f269e3021894 | 71 | /* SPI 1 selected */ |
elessair | 0:f269e3021894 | 72 | CLOCK_ENABLE(CLOCK_SPI); /* Enable clock */ |
elessair | 0:f269e3021894 | 73 | } else { |
elessair | 0:f269e3021894 | 74 | /* SPI 2 selected */ |
elessair | 0:f269e3021894 | 75 | CLOCK_ENABLE(CLOCK_SPI2); /* Enable clock */ |
elessair | 0:f269e3021894 | 76 | } |
elessair | 0:f269e3021894 | 77 | |
elessair | 0:f269e3021894 | 78 | CLOCK_ENABLE(CLOCK_CROSSB); |
elessair | 0:f269e3021894 | 79 | /* Cross bar setting: Map GPIOs to SPI */ |
elessair | 0:f269e3021894 | 80 | pinmap_pinout(sclk, PinMap_SPI_SCLK); |
elessair | 0:f269e3021894 | 81 | pinmap_pinout(mosi, PinMap_SPI_MOSI); |
elessair | 0:f269e3021894 | 82 | |
elessair | 0:f269e3021894 | 83 | /* Configure GPIO Direction */ |
elessair | 0:f269e3021894 | 84 | CLOCK_ENABLE(CLOCK_GPIO); |
elessair | 0:f269e3021894 | 85 | GPIOREG->W_OUT |= ((True << sclk) | (True << mosi) | (True << ssel)); /* Set pins as output */ |
elessair | 0:f269e3021894 | 86 | GPIOREG->W_IN |= (True << miso); /* Set pin as input */ |
elessair | 0:f269e3021894 | 87 | |
elessair | 0:f269e3021894 | 88 | /* Pad settings */ |
elessair | 0:f269e3021894 | 89 | CLOCK_ENABLE(CLOCK_PAD); |
elessair | 0:f269e3021894 | 90 | pin_mode(sclk, PushPullPullDown); |
elessair | 0:f269e3021894 | 91 | pin_mode(mosi, PushPullPullDown); |
elessair | 0:f269e3021894 | 92 | |
elessair | 0:f269e3021894 | 93 | /* PAD drive strength */ |
elessair | 0:f269e3021894 | 94 | PadReg_t *padRegOffset = (PadReg_t*)(PADREG_BASE + (sclk * PAD_REG_ADRS_BYTE_SIZE)); |
elessair | 0:f269e3021894 | 95 | padRegOffset->PADIO0.BITS.POWER = True; /* sclk: Drive strength */ |
elessair | 0:f269e3021894 | 96 | padRegOffset->PADIO1.BITS.POWER = True; /* mosi: Drive strength */ |
elessair | 0:f269e3021894 | 97 | if(miso != NC) { |
elessair | 0:f269e3021894 | 98 | pinmap_pinout(miso, PinMap_SPI_MISO); /* Cross bar settings */ |
elessair | 0:f269e3021894 | 99 | pin_mode(miso, OpenDrainNoPull); /* Pad setting */ |
elessair | 0:f269e3021894 | 100 | padRegOffset->PADIO2.BITS.POWER = True; /* miso: Drive strength */ |
elessair | 0:f269e3021894 | 101 | } |
elessair | 0:f269e3021894 | 102 | if(ssel != NC) { |
elessair | 0:f269e3021894 | 103 | pinmap_pinout(ssel, PinMap_SPI_SSEL); /* Cross bar settings */ |
elessair | 0:f269e3021894 | 104 | pin_mode(ssel, PushPullPullUp); /* Pad setting */ |
elessair | 0:f269e3021894 | 105 | padRegOffset->PADIO3.BITS.POWER = True; /* ssel: Drive strength */ |
elessair | 0:f269e3021894 | 106 | SPI1REG->SLAVE_SELECT.BITS.SS_ENABLE = SPI_SLAVE_SELECT_NORM_BEHAVE; /* Slave select: Normal behavior */ |
elessair | 0:f269e3021894 | 107 | } |
elessair | 0:f269e3021894 | 108 | CLOCK_DISABLE(CLOCK_PAD); |
elessair | 0:f269e3021894 | 109 | CLOCK_DISABLE(CLOCK_GPIO); |
elessair | 0:f269e3021894 | 110 | CLOCK_DISABLE(CLOCK_CROSSB); |
elessair | 0:f269e3021894 | 111 | |
elessair | 0:f269e3021894 | 112 | /* disable/reset the spi port: Clear control register*/ |
elessair | 0:f269e3021894 | 113 | obj->membase->CONTROL.WORD = False; |
elessair | 0:f269e3021894 | 114 | |
elessair | 0:f269e3021894 | 115 | /* set default baud rate to 1MHz */ |
elessair | 0:f269e3021894 | 116 | clockDivisor = ((fClockGetPeriphClockfrequency() / SPI_DEFAULT_SPEED) >> True) - True; |
elessair | 0:f269e3021894 | 117 | obj->membase->FDIV = clockDivisor; |
elessair | 0:f269e3021894 | 118 | |
elessair | 0:f269e3021894 | 119 | /* set tx/rx fifos watermarks */ /* TODO water mark level 1 byte ?*/ |
elessair | 0:f269e3021894 | 120 | obj->membase->TX_WATERMARK = True; |
elessair | 0:f269e3021894 | 121 | obj->membase->RX_WATERMARK = True; |
elessair | 0:f269e3021894 | 122 | |
elessair | 0:f269e3021894 | 123 | /* DIsable and clear IRQs */ /* TODO sync api, do not need irq ?*/ |
elessair | 0:f269e3021894 | 124 | obj->membase->IRQ_ENABLE = False; |
elessair | 0:f269e3021894 | 125 | obj->membase->IRQ_CLEAR = SPI_BYTE_MASK; /* Clear all */ |
elessair | 0:f269e3021894 | 126 | |
elessair | 0:f269e3021894 | 127 | /* configure slave select */ |
elessair | 0:f269e3021894 | 128 | obj->membase->SLAVE_SELECT.WORD = SPI_SLAVE_SELECT_DEFAULT; |
elessair | 0:f269e3021894 | 129 | obj->membase->SLAVE_SELECT_POLARITY = False; |
elessair | 0:f269e3021894 | 130 | |
elessair | 0:f269e3021894 | 131 | /* Configure control register parameters: 8 bits, master, CPOL = 0, Idle low. CPHA = 0, First transmit occurs before first edge of SCLK. MSB first. Sample incoming data on opposite edge of SCLK from when outgoing data is driven. enable the spi port */ |
elessair | 0:f269e3021894 | 132 | obj->membase->CONTROL.WORD = SPI_DEFAULT_CONFIG; |
elessair | 0:f269e3021894 | 133 | } |
elessair | 0:f269e3021894 | 134 | |
elessair | 0:f269e3021894 | 135 | /** Close a spi device. |
elessair | 0:f269e3021894 | 136 | * @details |
elessair | 0:f269e3021894 | 137 | * |
elessair | 0:f269e3021894 | 138 | * @param obj The spi device to close. |
elessair | 0:f269e3021894 | 139 | * @return None |
elessair | 0:f269e3021894 | 140 | */ |
elessair | 0:f269e3021894 | 141 | void fSpiClose(spi_t *obj) |
elessair | 0:f269e3021894 | 142 | { |
elessair | 0:f269e3021894 | 143 | /* disable the spi port */ |
elessair | 0:f269e3021894 | 144 | obj->membase->CONTROL.BITS.ENABLE = False; |
elessair | 0:f269e3021894 | 145 | |
elessair | 0:f269e3021894 | 146 | /* disable interruption associated with spi */ |
elessair | 0:f269e3021894 | 147 | NVIC_DisableIRQ(obj->irq); |
elessair | 0:f269e3021894 | 148 | } |
elessair | 0:f269e3021894 | 149 | |
elessair | 0:f269e3021894 | 150 | /** |
elessair | 0:f269e3021894 | 151 | * Write data to an SPI device. |
elessair | 0:f269e3021894 | 152 | * The data is written from the buffer into the transmit register. |
elessair | 0:f269e3021894 | 153 | * This function blocks untill write and read happens. |
elessair | 0:f269e3021894 | 154 | * |
elessair | 0:f269e3021894 | 155 | * @param obj The device to write to. |
elessair | 0:f269e3021894 | 156 | * @param buf The buffer to write from (the contents of the buffer may not be modified). |
elessair | 0:f269e3021894 | 157 | * @return the value received during send |
elessair | 0:f269e3021894 | 158 | */ |
elessair | 0:f269e3021894 | 159 | int fSpiWriteB(spi_t *obj, uint32_t const buf) |
elessair | 0:f269e3021894 | 160 | { |
elessair | 0:f269e3021894 | 161 | int byte; |
elessair | 0:f269e3021894 | 162 | |
elessair | 0:f269e3021894 | 163 | while((obj->membase->STATUS.BITS.TX_FULL == True) && (obj->membase->STATUS.BITS.RX_FULL == True)); /* Wait till Tx/Rx status is full */ |
elessair | 0:f269e3021894 | 164 | obj->membase->TX_DATA = buf; |
elessair | 0:f269e3021894 | 165 | |
elessair | 0:f269e3021894 | 166 | while (obj->membase->STATUS.BITS.RX_EMPTY == True); /* Wait till Receive status is empty */ |
elessair | 0:f269e3021894 | 167 | byte = obj->membase->RX_DATA; |
elessair | 0:f269e3021894 | 168 | return byte; |
elessair | 0:f269e3021894 | 169 | } |
elessair | 0:f269e3021894 | 170 | |
elessair | 0:f269e3021894 | 171 | #endif /* DEVICE_SPI */ |