ssp0.c (7259B)
1 /**************************************************************************/ 2 /*! 3 @file ssp0.c 4 @author K. Townsend (microBuilder.eu) 5 6 @section LICENSE 7 8 Software License Agreement (BSD License) 9 10 Copyright (c) 2012, K. Townsend (microBuilder.eu) 11 All rights reserved. 12 13 Redistribution and use in source and binary forms, with or without 14 modification, are permitted provided that the following conditions are met: 15 1. Redistributions of source code must retain the above copyright 16 notice, this list of conditions and the following disclaimer. 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in the 19 documentation and/or other materials provided with the distribution. 20 3. Neither the name of the copyright holders nor the 21 names of its contributors may be used to endorse or promote products 22 derived from this software without specific prior written permission. 23 24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 25 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 28 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 /**************************************************************************/ 36 #include "projectconfig.h" 37 38 #include "core/gpio/gpio.h" 39 #include "core/ssp0/ssp0.h" 40 41 /**************************************************************************/ 42 /*! 43 Set SSP clock to slow (400 KHz) 44 */ 45 /**************************************************************************/ 46 void ssp0ClockSlow() 47 { 48 /* Divide by 15 for SSPCLKDIV */ 49 LPC_SYSCON->SSP0CLKDIV = SCB_CLKDIV_DIV15; 50 51 /* (PCLK / (CPSDVSR * [SCR+1])) = (4,800,000 / (2 x [5 + 1])) = 400 KHz */ 52 LPC_SSP0->CR0 = ( (7u << 0) // Data size = 8-bit (bits 3:0) 53 | (0 << 4) // Frame format = SPI (bits 5:4) 54 #if CFG_SSP_CPOL0 == 1 55 | (1 << 6) // CPOL = 1 (bit 6) 56 #else 57 | (0 << 6) // CPOL = 0 (bit 6) 58 #endif 59 #if CFG_SSP_CPHA0 == 1 60 | (1 << 7) // CPHA = 1 (bit 7) 61 #else 62 | (0 << 7) // CPHA = 0 (bit 7) 63 #endif 64 | SSP0_SCR_5); // Clock rate = 5 (bits 15:8) 65 66 /* Clock prescale register must be even and at least 2 in master mode */ 67 LPC_SSP0->CPSR = 2; 68 } 69 70 /**************************************************************************/ 71 /*! 72 Set SSP clock to fast (6.0 MHz) 73 */ 74 /**************************************************************************/ 75 void ssp0ClockFast() 76 { 77 /* Divide by 1 for SSPCLKDIV */ 78 LPC_SYSCON->SSP0CLKDIV = SCB_CLKDIV_DIV1; 79 80 /* (PCLK / (CPSDVSR * [SCR+1])) = (72,000,000 / (2 * [5 + 1])) = 6.0 MHz */ 81 LPC_SSP0->CR0 = ( (7u << 0) // Data size = 8-bit (bits 3:0) 82 | (0 << 4) // Frame format = SPI (bits 5:4) 83 #if CFG_SSP_CPOL0 == 1 84 | (1 << 6) // CPOL = 1 (bit 6) 85 #else 86 | (0 << 6) // CPOL = 0 (bit 6) 87 #endif 88 #if CFG_SSP_CPHA0 == 1 89 | (1 << 7) // CPHA = 1 (bit 7) 90 #else 91 | (0 << 7) // CPHA = 0 (bit 7) 92 #endif 93 | SSP0_SCR_5); // Clock rate = 5 (bits 15:8) 94 95 /* Clock prescale register must be even and at least 2 in master mode */ 96 LPC_SSP0->CPSR = 2; 97 } 98 99 /**************************************************************************/ 100 /*! 101 @brief Initialise SSP0 102 */ 103 /**************************************************************************/ 104 void ssp0Init(void) 105 { 106 uint8_t i, Dummy=Dummy; 107 108 /* Reset SSP */ 109 LPC_SYSCON->PRESETCTRL &= ~0x1; 110 LPC_SYSCON->PRESETCTRL |= 0x01; 111 112 /* Enable AHB clock to the SSP domain. */ 113 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 11); 114 115 /* Set P0.8 to SSP MISO0 */ 116 LPC_IOCON->PIO0_8 &= ~0x07; 117 LPC_IOCON->PIO0_8 |= 0x01; 118 119 /* Set P0.9 to SSP MOSI0 */ 120 LPC_IOCON->PIO0_9 &= ~0x07; 121 LPC_IOCON->PIO0_9 |= 0x01; 122 123 /* No LPC_IOCON->SCKLOC register on LPC11Uxx/13Uxx? */ 124 #if (CFG_SSP_SCK0_LOCATION == CFG_SSP_SCK0_1_29) 125 /* Set 1.29 to SSP SCK0 (0.6 is often used by USB and 0.10 for SWD) */ 126 LPC_IOCON->PIO1_29 = 0x01; 127 #elif (CFG_SSP_SCK0_LOCATION == CFG_SSP_SCK0_0_10) 128 /* Set 0.10 to SSP SCK0 (may be required for SWD!) */ 129 LPC_IOCON->SWCLK_PIO0_10 = 0x02; 130 #elif (CFG_SSP_SCK0_LOCATION == CFG_SSP_SCK0_0_6) 131 /* Set 0.6 to SSP SCK0 (may be required for USB!) */ 132 LPC_IOCON->PIO0_6 = 0x02; 133 #else 134 #error "Invalid CFG_SSP_SCK0_LOCATION" 135 #endif 136 137 /* Set SPI clock to high-speed by default */ 138 ssp0ClockFast(); 139 140 /* Clear the Rx FIFO */ 141 for ( i = 0; i < SSP0_FIFOSIZE; i++ ) 142 { 143 Dummy = LPC_SSP0->DR; 144 } 145 146 /* Enable device and set it to slave mode, no loopback */ 147 LPC_SSP0->CR1 = SSP0_CR1_SSE_ENABLED | SSP0_CR1_MS_SLAVE | SSP0_CR1_LBM_NORMAL; 148 } 149 150 /**************************************************************************/ 151 /*! 152 @brief Sends a block of data using SSP0 153 154 @param[in] buf 155 Pointer to the data buffer 156 @param[in] length 157 Block length of the data buffer 158 */ 159 /**************************************************************************/ 160 void ssp0Send (uint8_t *buf, uint32_t length) 161 { 162 uint32_t i; 163 uint8_t Dummy = Dummy; 164 165 for (i = 0; i < length; i++) 166 { 167 /* Move on only if NOT busy and TX FIFO not full. */ 168 while ((LPC_SSP0->SR & (SSP0_SR_TNF_NOTFULL | SSP0_SR_BSY_BUSY)) != SSP0_SR_TNF_NOTFULL); 169 LPC_SSP0->DR = *buf; 170 buf++; 171 172 while ( (LPC_SSP0->SR & (SSP0_SR_BSY_BUSY|SSP0_SR_RNE_NOTEMPTY)) != SSP0_SR_RNE_NOTEMPTY ); 173 /* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO 174 on MISO. Otherwise, when sspReceive is called, previous data byte 175 is left in the FIFO. */ 176 Dummy = LPC_SSP0->DR; 177 } 178 179 return; 180 } 181 182 /**************************************************************************/ 183 /*! 184 @brief Receives a block of data using SSP0 185 186 @param[in] buf 187 Pointer to the data buffer 188 @param[in] length 189 Block length of the data buffer 190 */ 191 /**************************************************************************/ 192 void ssp0Receive(uint8_t *buf, uint32_t length) 193 { 194 uint32_t i; 195 196 for ( i = 0; i < length; i++ ) 197 { 198 /* As long as the receive FIFO is not empty, data can be received. */ 199 LPC_SSP0->DR = 0xFF; 200 201 /* Wait until the Busy bit is cleared */ 202 while ( (LPC_SSP0->SR & (SSP0_SR_BSY_BUSY|SSP0_SR_RNE_NOTEMPTY)) != SSP0_SR_RNE_NOTEMPTY ); 203 204 *buf = LPC_SSP0->DR; 205 buf++; 206 } 207 208 return; 209 }