External flash control via kinetis M series SPI module

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

External flash control via kinetis M series SPI module

External flash control via kinetis M series SPI module

  1. Abstract

        Kinetis M series MCU is Freescale’s Metrology microcontrollers based on ARM Cortex M0+ cores. The SPI module of KM provides for full-duplex, synchronous, serial communication between the MCU and peripheral devices, it also has programmable 8 or 16 bit data transmission length, 64bit FIFO mode for data transfers, DMA transmit and receive features, single wire bidirectional mode, etc. This document is mainly use the KM34Z256VLQ7 SPI module realize the erase, program and read operation in external flash MX25L6404EM2I, it also gives sample code of the detail command external flash operation, and at last, print the testing code via UART.

pastedImage_0.jpg

1.SPI pin assignment and basic code

(1) SPI pin assignment

SPI signal

Pin name

Description

SPI_SS

PTD1

Slave select

SPI_SCK

PTD2

SPI serial clock

SPI_MOSI

PTD3

Master data out, slave data in

SPI_MISO

PTD4

Master data in, slave data out

External flash MX25L6404EM2I circuit:

pastedImage_6.jpg

(2) SPI initialization

  SPI initialization configuration the SPI pin, SPI module baud, master or slave mode, module enable, etc. the code just as following:

SIM_SCGC4 |= SIM_SCGC4_SPI0_MASK|SIM_SCGC4_SPI1_MASK;                            

SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;

void serial_flash_init(void)

{

    PORTD_PCR1 &= ~PORT_PCR_MUX_MASK;       

    PORTD_PCR1 |= PORT_PCR_MUX(1) |0X03;                                           //Use PTD1 as SPI0_SS  // configure it as the GPIO

    PORTD_PCR2 &= ~PORT_PCR_MUX_MASK;

    PORTD_PCR2 |= PORT_PCR_MUX(3) |0X03;                                           //Use PTD2 as SPI0_SCK

    PORTD_PCR3 &= ~PORT_PCR_MUX_MASK;

    PORTD_PCR3 |= PORT_PCR_MUX(3) |0X03;                                           //Use PTD3 as SPI0_MOSI 

    PORTD_PCR4 &= ~PORT_PCR_MUX_MASK;

    PORTD_PCR4 = PORT_PCR_MUX(3) |0X03;                                            //Use PTD4 as SPI0_MISO

    GPIOD_PDDR |=  0X02; // SS pin output

    GPIOD_PDOR |=  0X02; //  SS pin high

    SPI0_C1 |= SPI_C1_MSTR_MASK; // SPI0 master mode

                       

    SPI0_BR = 0x43;  //SPPR = 4, SPR = 3, bps div = (SPPR+1)*2^(SPR+1) = 80, baudrate= 24Mhz/80=300khz

    SPI0_C1 |= SPI_C1_SSOE_MASK;                         

    SPI0_C1 &= (~SPI_C1_CPHA_MASK);  // clock polarity

    SPI0_C1 &= (~SPI_C1_CPOL_MASK);  //clock phase

    SPI0_C1 &= (~SPI_C1_LSBFE_MASK);  // LSB:most significant

    SPI0_C1 &= (~SPI_C1_SPIE_MASK);                  //Disable RX interrrupt 

    SPI0_C1 &= (~SPI_C1_SPTIE_MASK);         //Disable the transmit interrupt

    SPI0_C2 |= SPI_C2_MODFEN_MASK;

       

    SPI0_C1 |= SPI_C1_SPE_MASK;  // enable SPI module

}

(3) One byte transfer code

uint8 hal_spi_transfer_one_byte(uint8 v)

{

   int dummy =0;

   char buff=0;

   while ((SPI0_S & SPI_S_SPTEF_MASK) == 0)  // wait for transmit buffer empty

   {

                dummy++;

    }

   dummy = SPI0_S;

   SPI0_DL = v;   // send one byte to transmit buffer

   while ((SPI0_S & SPI_S_SPRF_MASK) == 0); // wait ready buffer full

   buff = SPI0_DL;  // read one received byte

   return buff;         // return the received byte

  }

3 Code realization for external flash operation command

    At first, refer to the external flash program / erase flow, then I will give the according command code realization one by one.

pastedImage_0.jpg

Take flash sector erase flow as an example, the according code is :

void hal_spi_dev_flash_erase_sector(uint8 addr)

{

write_enable();      // WREN command

spi_wait(WEL);     // RDSR command and wait WEL=1

hal_spi_transfe_start();    // enable CS pin , CS=0

hal_spi_transfer_one_byte(CMD_SECTOR_ERASE);   // erase one sector (4KByte)command

hal_spi_transfer_one_byte(addr>>16);  // address

hal_spi_transfer_one_byte(addr>>8);

hal_spi_transfer_one_byte(addr>>0);

hal_spi_transfe_stop();  // disable CS pin, CS=1

spi_wait(WIP);    // RDSR command and wait WIP=0;

  }

(1)Write enable (WREN) command : 0X06

pastedImage_4.jpg

static void write_enable(void)

{

    hal_spi_transfe_start();  // enable CS pin , CS=0

    hal_spi_transfer_one_byte(CMD_WRITE_EN);  // Send WREN command

    hal_spi_transfe_stop();  // disable CS pin, CS=1

  }

(2)Read status register (RDSR) sequence: 0X05

pastedImage_3.jpg

static void spi_wait(uint8 CMD)

{

if(CMD == WEL)

while(get_sr()&0x02 != 0x02); // wait until WEL bit =1

else if(CMD == WIP)

while(get_sr()&0x01 != 0x00); // wait until WIP bit =0

}

static uint8 get_sr(void)

{

    uint8 v;

    hal_spi_transfe_start(); // enable CS pin , CS=0

    hal_spi_transfer_one_byte(CMD_GET_SR);  // Send RDSR command

    v = hal_spi_transfer_one_byte(0x00); // read states register data

    hal_spi_transfe_stop();    // disable CS pin, CS=1

    return v;

  }

(3) Sector erase (SE) sequence: 0X20

pastedImage_2.jpg

hal_spi_transfe_start();    // enable CS pin , CS=0

hal_spi_transfer_one_byte(CMD_SECTOR_ERASE);   // erase one sector (4KByte)command

hal_spi_transfer_one_byte(addr>>16);  // address

hal_spi_transfer_one_byte(addr>>8);

hal_spi_transfer_one_byte(addr>>0);

  hal_spi_transfe_stop();  // disable CS pin, CS=1

(4) Page program (PP) sequence : 0x02

pastedImage_1.jpg

#define PAGE_SIZE 256  

    hal_spi_transfe_start();// enable CS pin , CS=0

hal_spi_transfer_one_byte(CMD_PROGRAM); //send flash program command

hal_spi_transfer_one_byte(addr>>16); // flash page base address

hal_spi_transfer_one_byte(addr>>8);

hal_spi_transfer_one_byte(addr>>0);

for(i=0;i<(PAGE_SIZE-1);i++) // send program data to the flash page

hal_spi_transfer_one_byte(buf[i]);

hal_spi_transfer_one_byte(buf[i]);

  hal_spi_transfe_stop();// disable CS pin, CS=1

(5) Read at higher Speed(FAST_READ) Sequence: 0X0B

pastedImage_0.jpg

void hal_spi_dev_flash_read_page(uint8 addr, char *buf)

{

int i;

hal_spi_transfe_start();  // enable CS pin , CS=0

hal_spi_transfer_one_byte(CMD_READ); // read command

hal_spi_transfer_one_byte(addr>>16);  // base address

hal_spi_transfer_one_byte(addr>>8);

hal_spi_transfer_one_byte(addr>>0);

hal_spi_transfer_one_byte(0x00); // dummy byte

for(i=0;i<(PAGE_SIZE-1);i++)    // read data back from the flash

buf[i] = hal_spi_transfer_one_byte(0x00);

buf[i] = hal_spi_transfer_one_byte(0x00);

hal_spi_transfe_stop();  // disable CS pin, CS=1

  }

4 Experimental result

The test code function is to realize one sector (4KB) erasing, then read one page (256Byte) and print it out, after that, program one page , read and print it out to check the data.

(1)The main function code is :

static char buf[256];

int i;

serial_flash_init();  // SPI initialization

hal_spi_dev_flash_erase_sector(0); // erase one sector(4KByte)

printf("reading page...\n");

hal_spi_dev_flash_read_page(0,buf); // read one page(256Byte)

print_buf(buf,PAGE_SIZE);  // print the read data out

printf("programing a page...\n");

for(i=0;i<256;i++)

buf[i] = i;     // define the data which will write to the flash

hal_spi_dev_flash_program_page(0,buf); // write 256BYTE to the flash page0

printf("clearing buffer..\n");

for(i=0;i<256;i++)    // clear buff

buf[i] = 0;

printf("reading page...\n");

hal_spi_dev_flash_read_page(0,buf); // read the page0 data out

print_buf(buf,PAGE_SIZE);  // print the read data out

  printf("demo end.\n");

(2) print test data

reading page...

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

0xFF,0xFF,0xFF,0xFF,  0xFF,0xFF,0xFF,0xFF, 

programing a page...

clearing buffer..

reading page...

0x0,0x1,0x2,0x3,  0x4,0x5,0x6,0x7, 

0x8,0x9,0xA,0xB,  0xC,0xD,0xE,0xF, 

0x10,0x11,0x12,0x13,  0x14,0x15,0x16,0x17, 

0x18,0x19,0x1A,0x1B,  0x1C,0x1D,0x1E,0x1F, 

0x20,0x21,0x22,0x23,  0x24,0x25,0x26,0x27, 

0x28,0x29,0x2A,0x2B,  0x2C,0x2D,0x2E,0x2F, 

0x30,0x31,0x32,0x33,  0x34,0x35,0x36,0x37, 

0x38,0x39,0x3A,0x3B,  0x3C,0x3D,0x3E,0x3F, 

0x40,0x41,0x42,0x43,  0x44,0x45,0x46,0x47, 

0x48,0x49,0x4A,0x4B,  0x4C,0x4D,0x4E,0x4F, 

0x50,0x51,0x52,0x53,  0x54,0x55,0x56,0x57, 

0x58,0x59,0x5A,0x5B,  0x5C,0x5D,0x5E,0x5F, 

0x60,0x61,0x62,0x63,  0x64,0x65,0x66,0x67, 

0x68,0x69,0x6A,0x6B,  0x6C,0x6D,0x6E,0x6F, 

0x70,0x71,0x72,0x73,  0x74,0x75,0x76,0x77, 

0x78,0x79,0x7A,0x7B,  0x7C,0x7D,0x7E,0x7F, 

0x80,0x81,0x82,0x83,  0x84,0x85,0x86,0x87, 

0x88,0x89,0x8A,0x8B,  0x8C,0x8D,0x8E,0x8F, 

0x90,0x91,0x92,0x93,  0x94,0x95,0x96,0x97, 

0x98,0x99,0x9A,0x9B,  0x9C,0x9D,0x9E,0x9F, 

0xA0,0xA1,0xA2,0xA3,  0xA4,0xA5,0xA6,0xA7, 

0xA8,0xA9,0xAA,0xAB,  0xAC,0xAD,0xAE,0xAF, 

0xB0,0xB1,0xB2,0xB3,  0xB4,0xB5,0xB6,0xB7, 

0xB8,0xB9,0xBA,0xBB,  0xBC,0xBD,0xBE,0xBF, 

0xC0,0xC1,0xC2,0xC3,  0xC4,0xC5,0xC6,0xC7, 

0xC8,0xC9,0xCA,0xCB,  0xCC,0xCD,0xCE,0xCF, 

0xD0,0xD1,0xD2,0xD3,  0xD4,0xD5,0xD6,0xD7, 

0xD8,0xD9,0xDA,0xDB,  0xDC,0xDD,0xDE,0xDF, 

0xE0,0xE1,0xE2,0xE3,  0xE4,0xE5,0xE6,0xE7, 

0xE8,0xE9,0xEA,0xEB,  0xEC,0xED,0xEE,0xEF, 

0xF0,0xF1,0xF2,0xF3,  0xF4,0xF5,0xF6,0xF7, 

0xF8,0xF9,0xFA,0xFB,  0xFC,0xFD,0xFE,0xFF, 

  demo end

From the print data, we can find the code can realize flash sector erasing , flash program and flash data read out, and the test result is correct.

The following wave is the page read data out after flash page program.

pastedImage_0.jpg

The attachment is the testing code.

Attachments
No ratings
Version history
Last update:
‎09-10-2020 02:32 AM
Updated by: