Created
March 5, 2016 23:37
-
-
Save anonymous/cdf7df4d4f457a1703dd to your computer and use it in GitHub Desktop.
Interfaces low cost SPI SRAM (or FRAM) to a MSP430G2553 LaunchPad board
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Inspired by Rick Kimball's 23K256 Test for MSP430F2013 | |
// This code was compiled using Energia and runs on a standard LaunchPad | |
// The basic SPI SRAM support fits into 290 bytes on MSP430G2553 | |
// Increases to 422 bytes with streaming test | |
//#include <msp430.h> | |
//#include <stdint.h> | |
// Compiled using Energia | |
// Note the changes BIT0 is now the DEBUG_PIN and BIT4 is the SS_PIN. | |
// This was done to avoid conflict with P1.1 which is usually used as uart RxD | |
enum { | |
POWER_PIN = BIT0, // we power the 23K256 chip from one of our GPIO pins | |
SS_PIN = BIT4, // CS , active low | |
DEBUG_PIN = BIT0, // toggle on and off marking time to write | |
DUMMY_BYTE = 0xFF // byte we send when we just want to read slave data | |
}; | |
static inline uint8_t RWData(uint8_t value); | |
void loop(); | |
#define powerOn P1OUT |= POWER_PIN | |
#define powerOff P1OUT &= ~POWER_PIN | |
#define ssSelect P1OUT &= ~SS_PIN | |
#define ssDeselect P1OUT |= SS_PIN | |
#define delay_1ms __delay_cycles(16000) | |
#define SR_WRITE_STATUS 0x01 | |
#define SR_WRITE 0x02 | |
#define SR_READ 0x03 | |
#define SR_READ_STATUS 0x05 | |
int spi_rx_data = 0 ; | |
// 23K256 Serial Ram functions | |
uint8_t SR_getMode(void) { // Read the Mode of the 23K256 | |
ssSelect; | |
RWData(SR_READ_STATUS); // 0x05 | |
uint8_t mode = RWData(DUMMY_BYTE); | |
ssDeselect; | |
return mode; | |
} | |
void SR_setMode(uint8_t mode) { // Write Mode to 23K256 | |
ssSelect; | |
RWData(SR_WRITE_STATUS); // 0x01 | |
RWData(mode); | |
ssDeselect; | |
} | |
static inline void SR_writestream(uint16_t addr) { // Write a stream to 23K256 | |
ssDeselect; // deselect if we are active | |
ssSelect; | |
RWData(0x02); // Send command | |
RWData(addr >> 8); // Send upper address | |
RWData(addr); // Send lower address | |
} | |
static inline void SR_readstream(uint16_t addr) { // Read a stream from 23K256 | |
ssDeselect; | |
ssSelect; | |
RWData(0x03); // Send command | |
RWData(addr >> 8); // Send upper address | |
RWData(addr); // Send lower address | |
} | |
//----------------------------------------------------------------- | |
// SPI Send / Receive | |
static inline uint8_t RWData(uint8_t value) | |
{ | |
UCB0TXBUF = value; | |
while (!(IFG2 & UCB0TXIFG)); // wait for buffer ready | |
{ } | |
while (!(IFG2 & UCB0RXIFG)); // USCI_A0 RX Received? | |
spi_rx_data = UCB0RXBUF; // Store received data | |
return spi_rx_data; | |
} | |
//----------------------------------------------------------------- | |
/* | |
int SPI_SR(int spi_tx_data) | |
{ | |
P1OUT &= (~BIT5); // Select Device | |
while (!(IFG2 & UCB0TXIFG)); // USCI_A0 TX buffer ready? | |
UCB0TXBUF = spi_tx_data; // Send data over SPI to Slave | |
while (!(IFG2 & UCB0RXIFG)); // USCI_A0 RX Received? | |
spi_rx_data = UCB0RXBUF; // Store received data | |
P1OUT |= (BIT5); // Unselect Device | |
return spi_rx_data; | |
} | |
*/ | |
//----------------------------------------------------------------- | |
// main | |
int main() { | |
// kill the watchdog timer | |
WDTCTL = WDTPW + WDTHOLD; | |
//---------------------------------------------------------------------------- | |
// Configure the Clock for 16 MHz | |
BCSCTL1 = CALBC1_16MHZ; | |
DCOCTL = CALDCO_16MHZ; | |
//--------------------------------------------------------------------- | |
// Configure Ports | |
P1SEL |= BIT5 + BIT6 + BIT7; | |
P1SEL2 |= BIT5 + BIT6 + BIT7; | |
P1DIR |= BIT0 + BIT4 + BIT5 + BIT7; | |
//--------------------------------------------------------------------- | |
// Set UCSWRST | |
UCB0CTL1 = UCSWRST; | |
//--------------------------------------------------------------------- | |
// Configure USCI B0 | |
UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master, Mode 1 - check phase | |
UCB0CTL1 |= UCSSEL_2; // SMCLK | |
UCB0BR0 |= 2; // 8MHz maximum | |
UCB0BR1 = 0; | |
//--------------------------------------------------------------------- | |
// activate | |
UCB0CTL1 &= ~UCSWRST; | |
//--------------------------------------------------------------------- | |
// Previous USI Initialisation for 2452, 2013 etc - Rick Kimball | |
//--------------------------------------------------------------------- | |
/* | |
// configure DCO clock to 16MHz | |
BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0; | |
if (CALBC1_16MHZ != 0xFF) { | |
DCOCTL = 0x00; | |
BCSCTL1 = CALBC1_16MHZ; | |
DCOCTL = CALDCO_16MHZ; | |
} | |
BCSCTL1 |= XT2OFF + DIVA_0; | |
BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1; | |
*/ | |
//--------------------------------------------------------------------- | |
// configure GPIO | |
// P1OUT = SS_PIN; // deselect CS, turn off power to 23K256 | |
// P1DIR = SS_PIN + POWER_PIN + DEBUG_PIN; | |
//--------------------------------------------------------------------- | |
/* | |
// configure USI - SPI Mode 1 @ 4MHz, clocked off SMCLK | |
USICTL0 |= USISWRST; | |
USICTL0 = USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE + USISWRST; | |
USICTL1 |= USICKPH; | |
USICKCTL = USIDIV_1 + USISSEL_2; | |
*/ | |
//--------------------------------------------------------------------- | |
/* | |
// Enable USI | |
USICTL0 &= ~USISWRST; | |
__enable_interrupt(); // Set global interrupt enable | |
*/ | |
//--------------------------------------------------------------------- | |
// toggle the power for the 23K256 | |
// powerOn; | |
// Assume power is permanenty on in this implementation | |
ssDeselect; | |
delay_1ms; | |
while (1) { | |
uint8_t chipMode; | |
// make sure there is a 23K256 chip and that | |
// is wired properly and in sequential mode | |
chipMode = SR_getMode(); | |
if (chipMode != 0x41) { | |
SR_setMode(0x41); | |
} else { | |
while (1) { | |
loop(); | |
} | |
} | |
} | |
} | |
#define BYTES_TO_STREAM 32768 // should be less <= 32768 | |
#define PATTERN_BYTE_VALUE 0x55 | |
//loop - write a test pattern and read it back | |
void loop() { | |
uint16_t i; | |
uint8_t storedValue = 0; | |
P1OUT |= DEBUG_PIN; // mark start of write for measurement with oscope | |
SR_writestream(0); // start writing at address 0 | |
for (i = 0; i < BYTES_TO_STREAM; ++i) { | |
RWData(PATTERN_BYTE_VALUE); | |
} | |
P1OUT &= ~DEBUG_PIN; // mark end of write for measurement with oscope | |
// verify the bytes we wrote were stored and retreived properly | |
SR_readstream(0); // start reading at address 0 | |
for (i = 0; i < BYTES_TO_STREAM; ++i) { | |
storedValue = RWData(DUMMY_BYTE); | |
// verify our test pattern | |
if (storedValue != PATTERN_BYTE_VALUE) { | |
// if values aren't the same an error occurred, | |
// turn off all leds, then sit and spin | |
P1OUT &= ~BIT6; | |
P1OUT &= ~DEBUG_PIN; | |
while (1) { | |
; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment