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