view flash.c @ 21:bd8e2cf04034

- Add flash erase, write & read commands (needs more work). - Split the buffer into argv/argc to make sub commands simpler.
author Daniel O'Connor <darius@dons.net.au>
date Thu, 15 Nov 2012 23:40:51 +1030
parents 58d76cf522ff
children a9cc07caa801
line wrap: on
line source

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

#include "stm32f10x.h"
#include "spi.h"
#include "flash.h"

#define FL_SELECT()	GPIO_ResetBits(GPIOA, GPIO_Pin_4)
#define FL_DESELECT()	GPIO_SetBits(GPIOA, GPIO_Pin_4)

static const char *flstattbl[] = {
    "BUSY",
    "WEL",
    "BP0",
    "BP1",
    "BP2",
    "BP3",
    "AAI",
    "BPL"
};
		
void
flashcmd(char **argv, int argc) {
    uint8_t status, tmp;

    if (argc == 0) {
	fputs("No command specified\r\n", stdout);
	return;
    }
    
    if (!strcmp(argv[0], "str")) {
	status = flashreadstatus();
	fputs("Status = ", stdout);
	for (unsigned int i = 0; i < sizeof(flstattbl) / sizeof(flstattbl[0]); i++)
	    if (status & 1 << i) {
		fputs(flstattbl[i], stdout);
		fputs(" ", stdout);
	    }
	printf("(0x%02x)\r\n", status);
    } else if (!strcmp(argv[0], "stw")) {
	if (argc != 2) {
	    fputs("Incorrect number of arguments\r\n", stdout);
	    return;
	}
	tmp = atoi(argv[1]);
	flashwritestatus(tmp);
	status = flashreadstatus();
	printf("Wrote 0x%02x to status, now 0x%02x\r\n", tmp, status);
    } else if (!strcmp(argv[0], "er")) {
	if (argc != 2) {
	    fputs("Incorrect number of arguments\r\n", stdout);
	    return;
	}
	tmp = atoi(argv[1]);
	flash4kerase(tmp);
	printf("Erased 0x%x\r\n", tmp);
    } else if (!strcmp(argv[0], "rd")) {
	if (argc != 2) {
	    fputs("Incorrect number of arguments\r\n", stdout);
	    return;
	}
	tmp = atoi(argv[1]);

	for (int i = 0; i < 16; i++)
	    printf("Read 0x%02x from 0x%06x\r\n", flashread(tmp + i), tmp + i);
	fputs("\r\n", stdout);
    } else if (!strcmp(argv[0], "wr")) {
	if (argc != 2) {
	    fputs("Incorrect number of arguments\r\n", stdout);
	    return;
	}

	tmp = atoi(argv[1]);

	for (int i = 0; i < 16; i++) {
	    printf("Writing 0x%02x to 0x%06x\r\n", tmp + i, i);
	    flashwrite(tmp + i, i);
	}
	
    } else if (!strcmp(argv[0], "id")) {
	printf("Flash ID = 0x%04hx (expect 0xbf41)\r\n", flashreadid());
    } else {
	fputs("Unknown sub command\r\n", stdout);
	return;
    }
}

void
flash4kerase(uint32_t addr) {
    uint8_t	cnt;
    
    flashenablewrite();			/* Enable writing */
    
    FL_SELECT();			/* Select device */

    SPI_WriteByte(FL_4KERASE);		/* Send command */
    SPI_WriteByte((addr & 0x00ff0000) >> 16);
    SPI_WriteByte((addr & 0x0000ff00) >> 8);
    SPI_WriteByte((addr & 0x000000ff)); /* Send address */
  
    FL_DESELECT();
    
    /* Wait for not BUSY */
    for (cnt = 0; (flashreadstatus() & FL_BUSY) != 0; cnt++)
	;

    //printf("cnt = %d\r\n", cnt);
}

uint16_t
flashreadid(void) {
    uint8_t	fac, dev;
    
    FL_SELECT();			/* Select device */

    SPI_WriteByte(FL_RDID);		/* Send command */
    SPI_WriteByte(0x00);		/* Send address cycles (ID data starts at 0) */
    SPI_WriteByte(0x00);
    SPI_WriteByte(0x00);
    fac = SPI_WriteByte(0x00);		/* Read ID */
    dev = SPI_WriteByte(0x00);
  
    FL_DESELECT();			/* De-select device */

    return fac << 8 | dev;
}

void
flashenablewrite(void) {
    FL_SELECT();			/* Select device */

    SPI_WriteByte(FL_WREN);		/* Send command */
  
    FL_DESELECT();			/* De-select device */
}

uint8_t
flashreadstatus(void) {
    uint8_t	status;
    
    FL_SELECT();			/* Select device */

    SPI_WriteByte(FL_RDSR);		/* Send command */
    SPI_WriteByte(0x00);		/* Send dummy byte for address cycle */
    status = SPI_WriteByte(0x00);	/* Read status */
  
    FL_DESELECT();			/* De-select device */

    return status;
}

void
flashwritestatus(uint8_t status) {
    /* Enable status write */
    FL_SELECT();			/* Select device */
    SPI_WriteByte(FL_EWSR);		/* Send command */
    SPI_WriteByte(0x00);		/* Send data byte */
    FL_DESELECT();

    /* Actually write status */
    FL_SELECT();			/* Re-select device for new command */			
    SPI_WriteByte(FL_WRSR);		/* Send command */
    SPI_WriteByte(status);		/* Send data byte */
    FL_DESELECT();			/* De-select device */
}

uint8_t
flashread(uint32_t addr) {
    uint8_t	data;
    
    FL_SELECT();			/* Select device */

    SPI_WriteByte(FL_READ);		/* Send command */
    SPI_WriteByte((addr & 0x00ff0000) >> 16);
    SPI_WriteByte((addr & 0x0000ff00) >> 8);
    SPI_WriteByte((addr & 0x000000ff)); /* Send address */
    data = SPI_WriteByte(0x00);		/* Read data */
  
    FL_DESELECT();			/* De-select device */

    return data;
}

void
flashwrite(uint32_t addr, uint8_t data) {
    flashenablewrite();			/* Enable writes */

    FL_SELECT();			/* Select device */

    SPI_WriteByte(FL_BYTEPROG);		/* Send command */
    SPI_WriteByte((addr & 0x00ff0000) >> 16);
    SPI_WriteByte((addr & 0x0000ff00) >> 8);
    SPI_WriteByte((addr & 0x000000ff)); /* Send address */
    SPI_WriteByte(data);		/* Write data */
  
    FL_DESELECT();			/* De-select device */
}