I'm using the MSP430F47187 with the 23LC1024 SRAM chip, trying to maximize data transmission rates through SPI to the SRAM. Basically I'm transmitting 12 bytes at a time - first byte is the command, next three are the address, and finally the last eight are the data but I'm noticing a relatively long dead time between each byte tranmission (roughly 3x the time it takes to transmit one byte). Is in something configurable in the MSP430 that I'm missing, or is that the nature of the chips? Here's the code I'm using:
(oh I'm using a 32kHz cyrstal, which translate to 1MHz on SMCLK)
void main(void) { // Setup leds P4OUT = 0x00; P4DIR = 0xFF; InitSram(); // Test Data char * testData [4] = {0xAB, 0xCD, 0xEF, 0x12}; char * dataRcvd [4] = {0x00, 0x00, 0x00, 0x00}; while(1) { // Begin test LED_OUTPUT &= ~(LED_YELLOW | LED_BLUE | LED_GREEN | LED_RED); dataRcvd[0] = 0x00; dataRcvd[1] = 0x00; dataRcvd[2] = 0x00; dataRcvd[3] = 0x00; LED_OUTPUT |= LED_YELLOW; // Write to SRAM WriteBlock(0, testData, 8); LED_OUTPUT &= ~LED_YELLOW; // Wait for it DelayOneSecond(); // Read it back and confirm ReadBlock(0, dataRcvd, 8); // Test! LED_OUTPUT &= ~(LED_YELLOW | LED_BLUE | LED_GREEN | LED_RED); if ( testData[0] == dataRcvd[0] && testData[1] == dataRcvd[1] && testData[2] == dataRcvd[2] && testData[3] == dataRcvd[3] ) { LED_OUTPUT |= LED_GREEN; } else { LED_OUTPUT |= LED_RED; } DelayOneSecond(); DelayOneSecond(); DelayOneSecond(); } // end while(1)
sram.h:
#ifndef SRAM_H_ #define SRAM_H_ #include <msp430f47187.h> #include "sensor_types.h" /** * Available modes of operation as found in the status register */ #define BYTE_MODE 0x00 #define SEQUENTIAL_MODE 0x40 #define PAGE_MODE 0x80 /** * The maximum address available on the chip * Attempts to read or write above this address will roll over back to that start * * Actual number of values is XXXXX, but in our case we are using a zero indexed value, * so the max address is XXXXX - 1. */ #define MAX_SRAM_ADDR 131071 /** * The chip select pin, located on Port 3 */ #define SRAM_CHIP_SELECT BIT2 /** * The SRAM HOLD pin located on Port 2 */ #define SRAM_HOLD BIT0 /** * A structure that holds a voltage and current sample pair for storage */ typedef struct { uint16_t voltage; uint16_t current; } WaveformData_t; /** * Available instructions that may be sent to the SRAM */ enum SRAM_CMDS { SRAM_WRITE_STATUS = 0x01, SRAM_WRITE_DATA = 0x02, SRAM_READ_DATA = 0x03, SRAM_READ_STATUS = 0x05, }; #define SRAM_WRITE_MODE SRAM_WRITE_STATUS #define SRAM_READ_MODE SRAM_READ_STATUS /** * Initialize all gpio, ports, and state variables used to control the SRAM */ void InitSram(); /** * Read back the status register from the SRAM chip * * STATUS REGISTER * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * | MODE | MODE | 0 | 0 | 0 | 0 | 1 | HOLD | * * Only the 7, 6 and 0 bit are writable */ uint8_t ReadSramStatus(); /** * Write a new value to the status register which controls the data mode and hold functionality */ void WriteSramStatus(uint8_t newStatus); /** * Read a data block from the SRAM chip starting at the supplied address */ WaveformData_t * ReadData(uint16_t address); /** * Write a data block to the SRAM chip starting at the supplied address */ void WriteData(uint16_t address, WaveformData_t * newData); #endif /* SRAM_H_ */
sram.c:
#include "sram.h" uint8_t rval; uint8_t mode; /* Pull the select down */ #define CS_LOW() P3OUT &= ~SRAM_CHIP_SELECT /* Pull select up */ #define CS_HIGH() P3OUT |= SRAM_CHIP_SELECT #define TESTDATA 0x32 uint8_t RWData(uint8_t value) { while ((UC1IFG & UCB1TXIFG) == 0) ; UCB1TXBUF = value; while ((UC1IFG & UCB1RXIFG) == 0) ; return UCB1RXBUF; } uint8_t GetMode(void) { RWData((uint8_t) SRAM_READ_MODE); // 0x05 uint8_t mode = RWData(0xFF); // Just read slave data return mode; } void SetMode(uint8_t mode) { RWData((uint8_t) SRAM_WRITE_MODE); // 0x01 RWData(mode); } /** * Initialize all gpio, ports, and state variables used to control the SRAM * The SRAM chip uses the UCB1 SPI port located on Port 2 * * p2.0 -> ~HOLD * p2.1 -> SI * p2.2 -> SO * p2.3 -> SCK * * p3.2 -> ~CS */ void InitSram() { /* Initialize SPI */ P2SEL |= BIT1 | BIT2 | BIT3; P2DIR |= BIT0; // As ouput P2OUT |= BIT0; // Set HOLD high P3OUT |= SRAM_CHIP_SELECT; // Set CS High P3DIR |= BIT2; // As output // configure USI - SPI Mode 1 @ 4MHz, clocked off SMCLK UCB1CTL1 |= UCSWRST; UCB1CTL0 |= UCSYNC + UCMST + UCMSB + UCMODE_0 + UCCKPH; UCB1CTL0 &= ~UCCKPL; UCB1CTL1 |= UCSSEL_2;//+UCSWRST; // Original clock setting UCB1BR0 |= 0x01; UCB1BR1 |= 0x00; UCB1CTL1 &= ~UCSWRST; CS_LOW(); // Must set CS low in order to write the read/write mode register SetMode(SEQUENTIAL_MODE); CS_HIGH(); // Set it high terminate read/write operation CS_LOW(); mode = GetMode(); CS_HIGH(); CS_LOW(); RWData(SRAM_WRITE_DATA); RWData(0); // Address location 0 RWData(0); // Address location 0 RWData(0); RWData('x'); // Write data RWData('y'); // Write data RWData('z'); // Write data CS_HIGH(); CS_LOW(); RWData(SRAM_READ_DATA); RWData(0); RWData(0); RWData(0); rval = RWData(0xFF); // Write 0xFF (dummy data) to read back value rval = RWData(0xFF); rval = RWData(0xFF); CS_HIGH(); } // end InitSram /** * Read a data block from the SRAM chip starting at the supplied address */ int ReadBlock(uint16_t address, char *buf, uint16_t size) //int ReadBlock(uint16_t address, uint8_t *buf, uint16_t size) { int i; CS_LOW(); RWData(SRAM_READ_DATA); RWData(0); RWData(address >> 8); RWData(address); for (i = 0; i < size; i++) buf[i] = RWData(0xFF); CS_HIGH(); return(i); } /** * Write a data block to the SRAM chip starting at the supplied address */ int WriteBlock(uint16_t address, char* buf, uint16_t size) //int WriteBlock(uint16_t address, uint8_t buf, uint16_t size) { int i; CS_LOW(); RWData(SRAM_WRITE_DATA); RWData(0); RWData(address >> 8); RWData(address); for (i = 0; i < size; i++) //RWData(buf[i]); RWData(TESTDATA); //RWData(buf); CS_HIGH(); return(i); }
Any ideas if this is doable?
Thanks.