Silicon Labs
|
Silicon Labs Community Silicon Labs Community
  • Products
    1. 8-bit MCU
    2. 32-bit MCU
    3. Bluetooth
    4. Proprietary
    5. Wi-Fi
    6. Zigbee & Thread
    7. Z-Wave
    8. Interface
    9. Isolation
    10. Power
    11. Sensors
    12. Timing
  • Development Tools
    1. Simplicity Studio
    2. Third Party Tools
  • Expert's Corner
    1. Announcements
    2. Blog
    3. General Interest
    4. Projects
How to Buy
English
  • English
  • 简体中文
  • 日本語
//
Community // Blog

Chapter 9.2: Store Lots of Data in an SPI Flash – Part 2: Connecting and Reading the JEDEC ID

01/26/2016 | 06:33 PM
lynchtron

Level 5


9.1_title.png

This is a five part series on the SPI communication protocol.  In the first section, we learned all about SPI and how to make a SPI flash breakout board from a bare chip.  In this section, we will connect the SPI flash to the EFM32 Starter Kit and then write some code with the help of the USART library to fetch the JEDEC ID from the register on the part.  We will continue to rely on the Spansion flash chip’s spec to accomplish this.

 

Flash Chip to MCU Connections

The SPI bus requires either three or four wires, depending on the mode. 

 9.1_spi_connection.png

I will demonstrate the use of SPI using the four-wire mode, which is more common in my experience than the three-wire mode.  The EFM32 USART supports the three-wire mode and calls this mode Synchronous Half Duplex Communication.  In that case, the MISO line is not used and the MOSI line becomes a bidirectional signal.  You can read more about it in the Reference Manual.

 

In SPI terminology, a SPI device can be a master or a slave device, at any given moment in time.  The USART peripheral in the EFM32 can be configured as either one.  One device has to be the master and the other a slave for a single SPI transaction.  We will configure the MCU as master since the MCU is driving the interaction with the flash chip.  We might someday configure the MCU as a slave if we have another MCU in a system and intend to share information between the two of them.  But we could configure our USART in the MCU dynamically to be a slave on one cycle, then a master on the next cycle.

 

The Master In Slave Out (MOSI) terminology is an improvement over the RX/TX nomenclature of the serial port connections.  Now, a master device’s MOSI output pin connects directly to a slave’s MOSI input pin, and MISO pin to MISO pin.  This is great, because the connections are made between like-named, or at least similarly-named pins.  Unfortunately the Data Sheet tables for the USART pins don’t specifically list MOSI/MISO, and you still need to know to map the USART TX pins to MOSI and the USART RX pins to MISO.  This information is covered in the Reference Manual for the USART peripheral.  In addition, some devices don’t use the MOSI/MISO naming and instead use SDI, DI, SI, etc. for an input.  If you can find the one that says input, attach that to the master’s MOSI and you will do fine.

 

The flash chip breakout board has additional signals that must be attached to your Starter Kit.  The first thing to look for are the power and ground connections.  Whenever you are connecting your MCU to an external device, you need to take a look at the voltage requirements in the spec for that device.  This is listed in the Electrical section for the Spansion chip.

 9.1_ratings.png

 

 

The Supply Voltage (also known as Vcc and sometimes called Vdd) requires between 2.7V and 3.8V.  Sometimes you will find chips that require 1.8V or 2.8V, which would then need an external power supply to be provided.  In this case, the chip can be powered directly from the Starter Kit’s 3.3V supply pins that are labeled as 3V3.  Connect the signals as shown in the table below.  We are using specific pins of USART1 location 1 for the SPI signals, since those are brought out to pins on the Starter Kit, and just any old GPIO’s for the other signals.

Signal

Spansion Flash Breakout Pin

Wonder Gecko GPIO Pin

CS# (Chip Select, active low)

1 – top left

PD3 – USART CS

SO (MISO)

2

PD1 – USART RX (MISO)

WP# (Write Protect, active low)

3

PD4 – Chosen at random

GND

4 – bottom left

GND

SI/SO (MOSI)

5 – bottom right

PD0 – USART TX (MOSI)

SCK (Clock)

6

PD2 – USART CLK

HOLD# (active low)

7

PD5 – Chosen at random

VCC

8 – top right

V3V

 

 9.1_efm32_connections.jpg

 

SPI Software Configuration

Now that everything is wired up, it is time to communicate with the flash memory chip from the MCU with software.  You can use Simplicity Configurator to configure the part like we did in the last lesson, or manually configure your USART to connect to the SPI signals CLK, CS, MOSI (TX in the USART) and MISO (RX in the USART).  I will demonstrate how to do it manually for this chapter.

 

There is a decision to be made about the clock mode when configuring the clock signal in the USART software setup.  With SPI, very little is set in stone.  It is up to the chip designers to determine exactly how the electrical signals should operate.  The USART provides configuration registers that handle the polarity and phase in order to work with all devices.  These are referred to as CPOL or CLKPOL (depending on the chip) for the clock polarity and CPHA or CLKPHA for the clock phase.  The clock polarity can be set to either 0 or 1, which determines the idle state of the clock line.  The clock phase can also be 0 or 1, which determines whether data is latched on the rising or falling edge of the clock signal.  This gives four possible choices for clock modes 0 through 3, which make up the four clock modes.  There are diagrams in the Reference Manual that describe all four modes. 


All that really matters to us at this point is that we pick the right mode for the Spansion chip.  If we look in the spec for the Spansion flash chip, we see that it can operate in either clock mode 0 or clock mode 3. 

 9.1_spec_waveforms.png

When configuring the CS line, there is a decision to be made about whether or not the USART peripheral will control the CS line automatically, known as AUTOCS, or if the software will explicitly control the CS line to the slave SPI device.  We will need to control the CS line explicitly, because if we were to pick AUTOCS mode and fail to feed the USART the two bytes of data fast enough, the USART-controlled CS line will go high in the middle of the above waveform, and the device will essentially forget all about the command we requested.  We need to drive the CS line low for the entire time as shown in the diagram.  The AUTOCS mode is better used when we are sending bytes to the USART through another hardware mechanism rather than software.

 

We will leave the SPI bus frequency at the default of 1MHz.  The table in the Spansion spec states that the chip supports SPI bus frequencies up to at least 44MHz, but you should be aware that the maximum that the EFM32 chip can reach is about one half of the HFPER clock frequency.  With the default HFRCO clock setup, that means it can only reach about 7MHz. Plus, our breadboard setup is more likely to see noise that could cause glitches at higher frequencies.

 

void usart_setup()
{
      // Set up the necessary peripheral clocks
      CMU_ClockEnable(cmuClock_GPIO, true);
      CMU_ClockEnable(cmuClock_USART1, true);
 
      // Enable the GPIO pins for the USART, starting with CS
      // This is to avoid clocking the flash chip when we set CLK high
      GPIO_PinModeSet(gpioPortD, 3, gpioModePushPull, 1);         // CS
      GPIO_PinModeSet(gpioPortD, 0, gpioModePushPull, 0);         // MOSI
      GPIO_PinModeSet(gpioPortD, 1, gpioModeInput, 0);            // MISO
      GPIO_PinModeSet(gpioPortD, 2, gpioModePushPull, 1);         // CLK
 
      // Enable the GPIO pins for the misc signals, leave pulled high
      GPIO_PinModeSet(gpioPortD, 4, gpioModePushPull, 1);         // WP#
      GPIO_PinModeSet(gpioPortD, 5, gpioModePushPull, 1);         // HOLD#
 
      // Initialize and enable the USART
      USART_InitSync_TypeDef init = USART_INITSYNC_DEFAULT;
      init.clockMode = usartClockMode3;
      init.msbf = true;
 
      USART_InitSync(USART1, &init);
 
      // Connect the USART signals to the GPIO peripheral
      USART1->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN |
                  USART_ROUTE_CLKPEN | USART_ROUTE_LOCATION_LOC1;
}


All of that work and we still don’t have anything that we can test to see if we did it right.  We still need some code to actually initiate a SPI cycle and we need to find a destination for that cycle that will yield a meaningful result to prove that the SPI command worked or not.  For this purpose, I turn to identification registers.  The chip designers of SPI parts will usually give you a softball register that always returns a non-zero fixed value to let you test basic connectivity and signs of life.  In this case, that register in the Spansion SPI Flash is the JEDEC ID at address 0x9F.  It actually has three distinct, non-zero fixed values that it can return one after another.  So we can test to make sure that we find the first value, then expand our test case to make sure that we find all three values.

 

#include "utilities.h"  // Re-used from earlier lesson for delay function
 
#define JEDEC_ID_CMD    0x9F
 
int main(void)
{
      CHIP_Init();
 
      usart_setup();
 
      setup_utilities();
 
      delay(100);
 
      uint8_t result[3];
      uint8_t index = 0;
 
      GPIO_PinModeSet(gpioPortD, 3, gpioModePushPull, 0);
 
      // Send the command, discard the first response
      USART_SpiTransfer(USART1, JEDEC_ID_CMD);
 
      // Now send garbage, but keep the results
      result[index++] = USART_SpiTransfer(USART1, 0);
      result[index++] = USART_SpiTransfer(USART1, 0);
      result[index++] = USART_SpiTransfer(USART1, 0);
 
      GPIO_PinModeSet(gpioPortD, 3, gpioModePushPull, 1);
 
      // Check the result for what is expected from the Spansion spec
      if (result[0] != 1 || result[1] != 0x40 || result[2] != 0x13)
      {
            DEBUG_BREAK
      }
 
      while (1)
            ;
}

 

Execute the code shown and break in on the while loop.  You should see a value of 1 in the result array at the 0 position.  This proves to a 1/254 chance that we are reading the register that we think we are reading.   Had this register’s default been zero or 0xff, we could not be sure that we were reading the right register because 0xff is the default state of flash memory at reset and zero is the usual default state for most configuration registers.  But since the default value for this Manufacturer ID is 1, we can be confident that this SPI driver is beginning to work.

 

You should notice something funny going on in this code.  We read a single value from the USART_SpiTransfer function and don’t do anything with the return value, then we read another value before storing the return value.  That is because a four-wire SPI bus is ALWAYS bidirectional.  When a master drives a cycle out on MOSI, the slave is required to drive something on MISO for every clock edge, even on the first clock.  But since the slave doesn’t even know what is being asked until after that first clock, the slave device will either send back a useless value, or sometimes slave devices will use this first bit time as a chance to send back a status message.   You have to examine the SPI chip’s spec to find out what it will do.  Once the command from the first bit time is latched and processed by the slave, it can respond with the necessary information on the second SPI transfer.

 

The code verifies that all three values from the JEDEC ID command are as expected, which gives us near certainty that we have indeed read from the Flash SPI device properly and the USART driver is working well so far.

 

In the next section, we will take a look at these SPI waveforms on the oscilloscopes and learn about more advanced SPI topology.

 

PREVIOUS I NEXT

  • Blog Posts
  • Makers
  • ipv6wiz

    Level 3


    Replied Jul 05 2017, 5:26 PM

    Hello,

     

    Where can I find your utilities routine that you mention you developed in an earlier exercise ?

     

     

    0

Tags

  • Wireless
  • High Performance Jitter Attenuators
  • EFR32FG22 Series 2 SoCs
  • EFR32MG21 Series 2 SoCs
  • Security
  • Bluegiga Legacy Modules
  • Zigbee SDK
  • ZigBee and Thread
  • EFR32BG13 Series 1 Modules
  • Internet Infrastructure
  • Sensors
  • Wireless Xpress BGX13
  • Blue Gecko Bluetooth Low Energy SoCs
  • Z-Wave
  • Micrium OS
  • Blog Posts
  • Low Jitter Clock Generators
  • Bluetooth Classic
  • Makers
  • Flex SDK
  • Tips and Tricks
  • timing
  • Smart Cities
  • Smart Homes
  • IoT Heroes
  • Reviews
  • RAIL
  • Simplicity Studio
  • Tiny Gecko
  • EFR32MG22 Series 2 SoCs
  • Mighty Gecko SoCs
  • Timing
  • Temperature Sensors
  • Blue Gecko Bluetooth Low Energy Modules
  • Ultra Low Jitter Clock Generators
  • General Purpose Clock Generators
  • EFR32BG22 Series 2 SoCs
  • Industry 4.0
  • Giant Gecko
  • 32-bit MCUs
  • Bluetooth Low Energy
  • 32-bit MCU SDK
  • Gecko
  • Microcontrollers
  • Jitter Attenuators
  • EFR32BG21 Series 2 SoCs
  • News and Events
  • Wi-Fi
  • Bluetooth SDK
  • Community Spotlight
  • Clock Generators
  • Biometric Sensors
  • General Purpose Jitter Attenuators
  • Giant Gecko S1
  • WF200
  • Flex Gecko
  • Internet of Things
  • 8-bit MCUs
  • Wireless Jitter Attenuators
  • Isolation
  • Powered Devices
  • Power

Top Authors

  • Avatar image Siliconlabs
  • Avatar image Jackie Padgett
  • Avatar image Nari Shin
  • Avatar image lynchtron
  • Avatar image deirdrewalsh
  • Avatar image Lance Looper
  • Avatar image lethawicker

Archives

  • 2016 March
  • 2016 April
  • 2016 May
  • 2016 June
  • 2016 July
  • 2016 August
  • 2016 September
  • 2016 October
  • 2016 November
  • 2016 December
  • 2017 January
  • 2017 February
  • 2017 March
  • 2017 April
  • 2017 May
  • 2017 June
  • 2017 July
  • 2017 August
  • 2017 September
  • 2017 October
  • 2017 November
  • 2017 December
  • 2018 January
  • 2018 February
  • 2018 March
  • 2018 April
  • 2018 May
  • 2018 June
  • 2018 July
  • 2018 August
  • 2018 September
  • 2018 October
  • 2018 November
  • 2018 December
  • 2019 January
  • 2019 February
  • 2019 March
  • 2019 April
  • 2019 May
  • 2019 June
  • 2019 July
  • 2019 August
  • 2019 September
  • 2019 October
  • 2019 November
  • 2019 December
  • 2020 January
  • 2020 February
  • 2020 March
  • 2020 April
  • 2020 May
  • 2020 June
  • 2020 July
  • 2020 August
  • 2020 September
  • 2020 October
  • 2020 November
  • 2020 December
  • 2021 January
  • 2021 February
Silicon Labs
Stay Connected With Us
Plug into the latest on Silicon Labs products, including product releases and resources, documentation updates, PCN notifications, upcoming events, and more.
  • About Us
  • Careers
  • Community
  • Contact Us
  • Corporate Responsibility
  • Privacy and Terms
  • Press Room
  • Investor Relations
  • Site Feedback
  • Cookies
Copyright © Silicon Laboratories. All rights reserved.
粤ICP备15107361号
Also of Interest:
  • Bring Your IoT Designs to Life with Smart,...
  • A Guide to IoT Protocols at Works With...
  • IoT Hero Rainus Enhances the In-Store Shopping...