update stm32f10x project directory structure.

This commit is contained in:
aozima 2013-07-12 18:14:39 +08:00
parent f0d03af696
commit 8c2a11c234
33 changed files with 62 additions and 2241 deletions

View File

@ -1,33 +1,14 @@
import rtconfig
# for module compiling
import os
Import('RTT_ROOT')
from building import *
src_bsp = ['application.c', 'startup.c', 'board.c', 'stm32f10x_it.c']
src_drv = ['rtc.c', 'usart.c', 'serial.c', 'led.c']
cwd = str(Dir('#'))
objs = []
list = os.listdir(cwd)
if GetDepend('RT_USING_DFS'):
if rtconfig.STM32_TYPE == 'STM32F10X_HD':
src_drv += ['sdcard.c']
else:
src_drv += ['msd.c']
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
if GetDepend('RT_USING_LWIP'):
src_drv += ['enc28j60.c'] + ['dm9000a.c']
if GetDepend('RT_USING_RTGUI'):
src_drv += ['touch.c']
if GetDepend('RT_USING_RTGUI'):
if rtconfig.RT_USING_LCD_TYPE == 'FMT0371':
src_drv += ['lcd_a70.c']
elif rtconfig.RT_USING_LCD_TYPE == 'ILI932X':
src_drv += ['ili_lcd_general.c']
elif rtconfig.RT_USING_LCD_TYPE == 'SSD1289':
src_drv += ['ssd1289.c']
src = src_bsp + src_drv
CPPPATH = [ GetCurrentDir() ]
CPPDEFINES = []
group = DefineGroup('Startup', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
Return('group')
Return('objs')

View File

@ -28,10 +28,8 @@ Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT)
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)
# STM32 firemare library building script
objs = objs + SConscript( GetCurrentDir() + '/Libraries/SConscript', variant_dir='build/bsp/Libraries', duplicate=0)
# make a building
DoBuilding(TARGET, objs)

View File

@ -0,0 +1,11 @@
Import('RTT_ROOT')
Import('rtconfig')
from building import *
cwd = os.path.join(str(Dir('#')), 'applications')
src = Glob('*.c')
CPPPATH = [cwd, str(Dir('#'))]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,40 @@
Import('RTT_ROOT')
Import('rtconfig')
from building import *
cwd = os.path.join(str(Dir('#')), 'drivers')
# add the general drvers.
src = Split("""
board.c
led.c
serial.c
usart.c
""")
# add Ethernet drvers.
if GetDepend('RT_USING_LWIP'):
src += ['dm9000a.c']
# add Ethernet drvers.
if GetDepend('RT_USING_DFS'):
src += ['sdcard.c']
# add Ethernet drvers.
if GetDepend('RT_USING_RTC'):
src += ['rtc.c']
# add Ethernet drvers.
if GetDepend('RT_USING_RTGUI'):
src += ['touch.c']
if rtconfig.RT_USING_LCD_TYPE == 'ILI932X':
src += ['ili_lcd_general.c']
elif rtconfig.RT_USING_LCD_TYPE == 'SSD1289':
src += ['ssd1289.c']
CPPPATH = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -1,779 +0,0 @@
/*
* File : enc28j60.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-05-05 Bernard the first version
*/
#include "enc28j60.h"
#include <netif/ethernetif.h>
#include <stm32f10x.h>
#include <stm32f10x_spi.h>
#define MAX_ADDR_LEN 6
#define CSACTIVE GPIOC->BRR = GPIO_Pin_12;
#define CSPASSIVE GPIOC->BSRR = GPIO_Pin_12;
struct net_device
{
/* inherit from ethernet device */
struct eth_device parent;
/* interface address info. */
rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
};
static struct net_device enc28j60_dev_entry;
static struct net_device *enc28j60_dev =&enc28j60_dev_entry;
static rt_uint8_t Enc28j60Bank;
static rt_uint16_t NextPacketPtr;
static struct rt_semaphore lock_sem;
void _delay_us(rt_uint32_t us)
{
rt_uint32_t len;
for (;us > 0; us --)
for (len = 0; len < 20; len++ );
}
void delay_ms(rt_uint32_t ms)
{
rt_uint32_t len;
for (;ms > 0; ms --)
for (len = 0; len < 100; len++ );
}
rt_uint8_t spi_read_op(rt_uint8_t op, rt_uint8_t address)
{
int temp=0;
CSACTIVE;
SPI_I2S_SendData(SPI1, (op | (address & ADDR_MASK)));
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);
SPI_I2S_ReceiveData(SPI1);
SPI_I2S_SendData(SPI1, 0x00);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);
// do dummy read if needed (for mac and mii, see datasheet page 29)
if(address & 0x80)
{
SPI_I2S_ReceiveData(SPI1);
SPI_I2S_SendData(SPI1, 0x00);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);
}
// release CS
temp=SPI_I2S_ReceiveData(SPI1);
// for(t=0;t<20;t++);
CSPASSIVE;
return (temp);
}
// ²ÎÊý: ÃüÁî,µØÖ·,Êý¾Ý
void spi_write_op(rt_uint8_t op, rt_uint8_t address, rt_uint8_t data)
{
rt_uint32_t level;
level = rt_hw_interrupt_disable();
CSACTIVE;
SPI_I2S_SendData(SPI1, op | (address & ADDR_MASK));
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);
SPI_I2S_SendData(SPI1,data);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);
CSPASSIVE;
rt_hw_interrupt_enable(level);
}
void enc28j60_set_bank(rt_uint8_t address)
{
// set the bank (if needed)
if((address & BANK_MASK) != Enc28j60Bank)
{
// set the bank
spi_write_op(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
Enc28j60Bank = (address & BANK_MASK);
}
}
rt_uint8_t spi_read(rt_uint8_t address)
{
// set the bank
enc28j60_set_bank(address);
// do the read
return spi_read_op(ENC28J60_READ_CTRL_REG, address);
}
void spi_read_buffer(rt_uint8_t* data, rt_size_t len)
{
CSACTIVE;
SPI_I2S_SendData(SPI1,ENC28J60_READ_BUF_MEM);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);
SPI_I2S_ReceiveData(SPI1);
while(len)
{
len--;
SPI_I2S_SendData(SPI1,0x00) ;
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);
*data= SPI_I2S_ReceiveData(SPI1);
data++;
}
CSPASSIVE;
}
void spi_write(rt_uint8_t address, rt_uint8_t data)
{
// set the bank
enc28j60_set_bank(address);
// do the write
spi_write_op(ENC28J60_WRITE_CTRL_REG, address, data);
}
void enc28j60_phy_write(rt_uint8_t address, rt_uint16_t data)
{
// set the PHY register address
spi_write(MIREGADR, address);
// write the PHY data
spi_write(MIWRL, data);
spi_write(MIWRH, data>>8);
// wait until the PHY write completes
while(spi_read(MISTAT) & MISTAT_BUSY)
{
_delay_us(15);
}
}
// read upper 8 bits
rt_uint16_t enc28j60_phy_read(rt_uint8_t address)
{
// Set the right address and start the register read operation
spi_write(MIREGADR, address);
spi_write(MICMD, MICMD_MIIRD);
_delay_us(15);
// wait until the PHY read completes
while(spi_read(MISTAT) & MISTAT_BUSY);
// reset reading bit
spi_write(MICMD, 0x00);
return (spi_read(MIRDH));
}
void enc28j60_clkout(rt_uint8_t clk)
{
//setup clkout: 2 is 12.5MHz:
spi_write(ECOCON, clk & 0x7);
}
rt_inline rt_uint32_t enc28j60_interrupt_disable()
{
rt_uint32_t level;
/* switch to bank 0 */
enc28j60_set_bank(EIE);
/* get last interrupt level */
level = spi_read(EIE);
/* disable interrutps */
spi_write_op(ENC28J60_BIT_FIELD_CLR, EIE, level);
return level;
}
rt_inline void enc28j60_interrupt_enable(rt_uint32_t level)
{
/* switch to bank 0 */
enc28j60_set_bank(EIE);
spi_write_op(ENC28J60_BIT_FIELD_SET, EIE, level);
}
/*
* Access the PHY to determine link status
*/
static rt_bool_t enc28j60_check_link_status()
{
rt_uint16_t reg;
int duplex;
reg = enc28j60_phy_read(PHSTAT2);
duplex = reg & PHSTAT2_DPXSTAT;
if (reg & PHSTAT2_LSTAT)
{
/* on */
return RT_TRUE;
}
else
{
/* off */
return RT_FALSE;
}
}
#ifdef RT_USING_FINSH
/*
* Debug routine to dump useful register contents
*/
static void enc28j60(void)
{
rt_kprintf("-- enc28j60 registers:\n");
rt_kprintf("HwRevID: 0x%02x\n", spi_read(EREVID));
rt_kprintf("Cntrl: ECON1 ECON2 ESTAT EIR EIE\n");
rt_kprintf(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",spi_read(ECON1), spi_read(ECON2), spi_read(ESTAT), spi_read(EIR), spi_read(EIE));
rt_kprintf("MAC : MACON1 MACON3 MACON4\n");
rt_kprintf(" 0x%02x 0x%02x 0x%02x\n", spi_read(MACON1), spi_read(MACON3), spi_read(MACON4));
rt_kprintf("Rx : ERXST ERXND ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL\n");
rt_kprintf(" 0x%04x 0x%04x 0x%04x 0x%04x ",
(spi_read(ERXSTH) << 8) | spi_read(ERXSTL),
(spi_read(ERXNDH) << 8) | spi_read(ERXNDL),
(spi_read(ERXWRPTH) << 8) | spi_read(ERXWRPTL),
(spi_read(ERXRDPTH) << 8) | spi_read(ERXRDPTL));
rt_kprintf("0x%02x 0x%02x 0x%04x\n", spi_read(ERXFCON), spi_read(EPKTCNT),
(spi_read(MAMXFLH) << 8) | spi_read(MAMXFLL));
rt_kprintf("Tx : ETXST ETXND MACLCON1 MACLCON2 MAPHSUP\n");
rt_kprintf(" 0x%04x 0x%04x 0x%02x 0x%02x 0x%02x\n",
(spi_read(ETXSTH) << 8) | spi_read(ETXSTL),
(spi_read(ETXNDH) << 8) | spi_read(ETXNDL),
spi_read(MACLCON1), spi_read(MACLCON2), spi_read(MAPHSUP));
}
#include <finsh.h>
FINSH_FUNCTION_EXPORT(enc28j60, dump enc28j60 registers);
#endif
/*
* RX handler
* ignore PKTIF because is unreliable! (look at the errata datasheet)
* check EPKTCNT is the suggested workaround.
* We don't need to clear interrupt flag, automatically done when
* enc28j60_hw_rx() decrements the packet counter.
*/
void enc28j60_isr()
{
/* Variable definitions can be made now. */
volatile rt_uint32_t eir, pk_counter;
volatile rt_bool_t rx_activiated;
rx_activiated = RT_FALSE;
/* get EIR */
eir = spi_read(EIR);
// rt_kprintf("eir: 0x%08x\n", eir);
do
{
/* errata #4, PKTIF does not reliable */
pk_counter = spi_read(EPKTCNT);
if (pk_counter)
{
/* a frame has been received */
eth_device_ready((struct eth_device*)&(enc28j60_dev->parent));
// switch to bank 0
enc28j60_set_bank(EIE);
// disable rx interrutps
spi_write_op(ENC28J60_BIT_FIELD_CLR, EIE, EIE_PKTIE);
}
/* clear PKTIF */
if (eir & EIR_PKTIF)
{
enc28j60_set_bank(EIR);
spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_PKTIF);
rx_activiated = RT_TRUE;
}
/* clear DMAIF */
if (eir & EIR_DMAIF)
{
enc28j60_set_bank(EIR);
spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_DMAIF);
}
/* LINK changed handler */
if ( eir & EIR_LINKIF)
{
enc28j60_check_link_status();
/* read PHIR to clear the flag */
enc28j60_phy_read(PHIR);
enc28j60_set_bank(EIR);
spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_LINKIF);
}
if (eir & EIR_TXIF)
{
/* A frame has been transmitted. */
enc28j60_set_bank(EIR);
spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXIF);
}
/* TX Error handler */
if ((eir & EIR_TXERIF) != 0)
{
enc28j60_set_bank(ECON1);
spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);
spi_write_op(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
enc28j60_set_bank(EIR);
spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF);
}
eir = spi_read(EIR);
// rt_kprintf("inner eir: 0x%08x\n", eir);
} while ((rx_activiated != RT_TRUE && eir != 0));
}
/* RT-Thread Device Interface */
/* initialize the interface */
rt_err_t enc28j60_init(rt_device_t dev)
{
CSPASSIVE;
// perform system reset
spi_write_op(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
delay_ms(50);
NextPacketPtr = RXSTART_INIT;
// Rx start
spi_write(ERXSTL, RXSTART_INIT&0xFF);
spi_write(ERXSTH, RXSTART_INIT>>8);
// set receive pointer address
spi_write(ERXRDPTL, RXSTOP_INIT&0xFF);
spi_write(ERXRDPTH, RXSTOP_INIT>>8);
// RX end
spi_write(ERXNDL, RXSTOP_INIT&0xFF);
spi_write(ERXNDH, RXSTOP_INIT>>8);
// TX start
spi_write(ETXSTL, TXSTART_INIT&0xFF);
spi_write(ETXSTH, TXSTART_INIT>>8);
// set transmission pointer address
spi_write(EWRPTL, TXSTART_INIT&0xFF);
spi_write(EWRPTH, TXSTART_INIT>>8);
// TX end
spi_write(ETXNDL, TXSTOP_INIT&0xFF);
spi_write(ETXNDH, TXSTOP_INIT>>8);
// do bank 1 stuff, packet filter:
// For broadcast packets we allow only ARP packtets
// All other packets should be unicast only for our mac (MAADR)
//
// The pattern to match on is therefore
// Type ETH.DST
// ARP BROADCAST
// 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
// in binary these poitions are:11 0000 0011 1111
// This is hex 303F->EPMM0=0x3f,EPMM1=0x30
spi_write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_BCEN);
// do bank 2 stuff
// enable MAC receive
spi_write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
// enable automatic padding to 60bytes and CRC operations
// spi_write_op(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
spi_write_op(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX);
// bring MAC out of reset
// set inter-frame gap (back-to-back)
// spi_write(MABBIPG, 0x12);
spi_write(MABBIPG, 0x15);
spi_write(MACON4, MACON4_DEFER);
spi_write(MACLCON2, 63);
// set inter-frame gap (non-back-to-back)
spi_write(MAIPGL, 0x12);
spi_write(MAIPGH, 0x0C);
// Set the maximum packet size which the controller will accept
// Do not send packets longer than MAX_FRAMELEN:
spi_write(MAMXFLL, MAX_FRAMELEN&0xFF);
spi_write(MAMXFLH, MAX_FRAMELEN>>8);
// do bank 3 stuff
// write MAC address
// NOTE: MAC address in ENC28J60 is byte-backward
spi_write(MAADR0, enc28j60_dev->dev_addr[5]);
spi_write(MAADR1, enc28j60_dev->dev_addr[4]);
spi_write(MAADR2, enc28j60_dev->dev_addr[3]);
spi_write(MAADR3, enc28j60_dev->dev_addr[2]);
spi_write(MAADR4, enc28j60_dev->dev_addr[1]);
spi_write(MAADR5, enc28j60_dev->dev_addr[0]);
/* output off */
spi_write(ECOCON, 0x00);
// enc28j60_phy_write(PHCON1, 0x00);
enc28j60_phy_write(PHCON1, PHCON1_PDPXMD); // full duplex
// no loopback of transmitted frames
enc28j60_phy_write(PHCON2, PHCON2_HDLDIS);
enc28j60_set_bank(ECON2);
spi_write_op(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_AUTOINC);
// switch to bank 0
enc28j60_set_bank(ECON1);
// enable interrutps
spi_write_op(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE|EIR_TXIF);
// enable packet reception
spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
/* clock out */
// enc28j60_clkout(2);
enc28j60_phy_write(PHLCON, 0xD76); //0x476
delay_ms(20);
return RT_EOK;
}
/* control the interface */
rt_err_t enc28j60_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
switch(cmd)
{
case NIOCTL_GADDR:
/* get mac address */
if(args) rt_memcpy(args, enc28j60_dev_entry.dev_addr, 6);
else return -RT_ERROR;
break;
default :
break;
}
return RT_EOK;
}
/* Open the ethernet interface */
rt_err_t enc28j60_open(rt_device_t dev, rt_uint16_t oflag)
{
return RT_EOK;
}
/* Close the interface */
rt_err_t enc28j60_close(rt_device_t dev)
{
return RT_EOK;
}
/* Read */
rt_size_t enc28j60_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
rt_set_errno(-RT_ENOSYS);
return 0;
}
/* Write */
rt_size_t enc28j60_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
rt_set_errno(-RT_ENOSYS);
return 0;
}
/* ethernet device interface */
/*
* Transmit packet.
*/
rt_err_t enc28j60_tx( rt_device_t dev, struct pbuf* p)
{
struct pbuf* q;
rt_uint32_t len;
rt_uint8_t* ptr;
rt_uint32_t level;
//rt_kprintf("tx pbuf: 0x%08x, total len %d\n", p, p->tot_len);
/* lock enc28j60 */
rt_sem_take(&lock_sem, RT_WAITING_FOREVER);
/* disable enc28j60 interrupt */
level = enc28j60_interrupt_disable();
// Set the write pointer to start of transmit buffer area
spi_write(EWRPTL, TXSTART_INIT&0xFF);
spi_write(EWRPTH, TXSTART_INIT>>8);
// Set the TXND pointer to correspond to the packet size given
spi_write(ETXNDL, (TXSTART_INIT+ p->tot_len + 1)&0xFF);
spi_write(ETXNDH, (TXSTART_INIT+ p->tot_len + 1)>>8);
// write per-packet control byte (0x00 means use macon3 settings)
spi_write_op(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
for (q = p; q != NULL; q = q->next)
{
CSACTIVE;
SPI_I2S_SendData(SPI1, ENC28J60_WRITE_BUF_MEM);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);
len = q->len;
ptr = q->payload;
while(len)
{
SPI_I2S_SendData(SPI1,*ptr) ;
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);;
ptr++;
len--;
}
CSPASSIVE;
}
// send the contents of the transmit buffer onto the network
spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
// Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
if( (spi_read(EIR) & EIR_TXERIF) )
{
spi_write_op(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
}
/* enable enc28j60 interrupt */
enc28j60_interrupt_enable(level);
rt_sem_release(&lock_sem);
return RT_EOK;
}
struct pbuf *enc28j60_rx(rt_device_t dev)
{
struct pbuf* p;
rt_uint32_t len;
rt_uint16_t rxstat;
rt_uint32_t pk_counter;
rt_uint32_t level;
p = RT_NULL;
/* lock enc28j60 */
rt_sem_take(&lock_sem, RT_WAITING_FOREVER);
/* disable enc28j60 interrupt */
level = enc28j60_interrupt_disable();
pk_counter = spi_read(EPKTCNT);
if (pk_counter)
{
// Set the read pointer to the start of the received packet
spi_write(ERDPTL, (NextPacketPtr));
spi_write(ERDPTH, (NextPacketPtr)>>8);
// read the next packet pointer
NextPacketPtr = spi_read_op(ENC28J60_READ_BUF_MEM, 0);
NextPacketPtr |= spi_read_op(ENC28J60_READ_BUF_MEM, 0)<<8;
// read the packet length (see datasheet page 43)
len = spi_read_op(ENC28J60_READ_BUF_MEM, 0); //0x54
len |= spi_read_op(ENC28J60_READ_BUF_MEM, 0) <<8; //5554
len-=4; //remove the CRC count
// read the receive status (see datasheet page 43)
rxstat = spi_read_op(ENC28J60_READ_BUF_MEM, 0);
rxstat |= ((rt_uint16_t)spi_read_op(ENC28J60_READ_BUF_MEM, 0))<<8;
// check CRC and symbol errors (see datasheet page 44, table 7-3):
// The ERXFCON.CRCEN is set by default. Normally we should not
// need to check this.
if ((rxstat & 0x80)==0)
{
// invalid
len=0;
}
else
{
/* allocation pbuf */
p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
if (p != RT_NULL)
{
rt_uint8_t* data;
struct pbuf* q;
for (q = p; q != RT_NULL; q= q->next)
{
data = q->payload;
len = q->len;
CSACTIVE;
SPI_I2S_SendData(SPI1,ENC28J60_READ_BUF_MEM);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);
SPI_I2S_ReceiveData(SPI1);
while(len)
{
len--;
SPI_I2S_SendData(SPI1,0x00) ;
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)==SET);
*data= SPI_I2S_ReceiveData(SPI1);
data++;
}
CSPASSIVE;
}
}
}
// Move the RX read pointer to the start of the next received packet
// This frees the memory we just read out
spi_write(ERXRDPTL, (NextPacketPtr));
spi_write(ERXRDPTH, (NextPacketPtr)>>8);
// decrement the packet counter indicate we are done with this packet
spi_write_op(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
}
else
{
// switch to bank 0
enc28j60_set_bank(ECON1);
// enable packet reception
spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
level |= EIE_PKTIE;
}
/* enable enc28j60 interrupt */
enc28j60_interrupt_enable(level);
rt_sem_release(&lock_sem);
return p;
}
static void RCC_Configuration(void)
{
//RCC_PCLK2Config ( uint32_t RCC_HCLK )
/* enable SPI1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
/* enable gpiob port clock */
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
}
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the EXTI0 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void GPIO_Configuration()
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/* configure PB0 as external interrupt */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure SPI1 pins: SCK, MISO and MOSI ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Connect ENC28J60 EXTI Line to GPIOB Pin 0 */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);
/* Configure ENC28J60 EXTI Line to generate an interrupt on falling edge */
EXTI_InitStructure.EXTI_Line = EXTI_Line2;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Clear the Key Button EXTI line pending bit */
EXTI_ClearITPendingBit(EXTI_Line2);
}
static void SetupSPI (void)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;//SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);
}
void rt_hw_enc28j60_init()
{
/* configuration PB5 as INT */
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
SetupSPI();
/* init rt-thread device interface */
enc28j60_dev_entry.parent.parent.init = enc28j60_init;
enc28j60_dev_entry.parent.parent.open = enc28j60_open;
enc28j60_dev_entry.parent.parent.close = enc28j60_close;
enc28j60_dev_entry.parent.parent.read = enc28j60_read;
enc28j60_dev_entry.parent.parent.write = enc28j60_write;
enc28j60_dev_entry.parent.parent.control = enc28j60_control;
enc28j60_dev_entry.parent.eth_rx = enc28j60_rx;
enc28j60_dev_entry.parent.eth_tx = enc28j60_tx;
/* Update MAC address */
/* OUI 00-04-A3 Microchip Technology, Inc. */
enc28j60_dev_entry.dev_addr[0] = 0x00;
enc28j60_dev_entry.dev_addr[1] = 0x04;
enc28j60_dev_entry.dev_addr[2] = 0xA3;
/* generate MAC addr (only for test) */
enc28j60_dev_entry.dev_addr[3] = 0x11;
enc28j60_dev_entry.dev_addr[4] = 0x22;
enc28j60_dev_entry.dev_addr[5] = 0x33;
rt_sem_init(&lock_sem, "lock", 1, RT_IPC_FLAG_FIFO);
eth_device_init(&(enc28j60_dev->parent), "e0");
}
#ifdef RT_USING_FINSH
#include <finsh.h>
void show_reg(void)
{
//
}
FINSH_FUNCTION_EXPORT(show_reg,show en28j60 regs)
#endif

View File

@ -1,315 +0,0 @@
/*
* File : enc28j60.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-01-05 Bernard the first version
*/
#ifndef __ENC28J60_H__
#define __ENC28J60_H__
#include <rtthread.h>
// ENC28J60 Control Registers
// Control register definitions are a combination of address,
// bank number, and Ethernet/MAC/PHY indicator bits.
// - Register address (bits 0-4)
// - Bank number (bits 5-6)
// - MAC/PHY indicator (bit 7)
#define ADDR_MASK 0x1F
#define BANK_MASK 0x60
#define SPRD_MASK 0x80
// All-bank registers
#define EIE 0x1B
#define EIR 0x1C
#define ESTAT 0x1D
#define ECON2 0x1E
#define ECON1 0x1F
// Bank 0 registers
#define ERDPTL (0x00|0x00)
#define ERDPTH (0x01|0x00)
#define EWRPTL (0x02|0x00)
#define EWRPTH (0x03|0x00)
#define ETXSTL (0x04|0x00)
#define ETXSTH (0x05|0x00)
#define ETXNDL (0x06|0x00)
#define ETXNDH (0x07|0x00)
#define ERXSTL (0x08|0x00)
#define ERXSTH (0x09|0x00)
#define ERXNDL (0x0A|0x00)
#define ERXNDH (0x0B|0x00)
#define ERXRDPTL (0x0C|0x00)
#define ERXRDPTH (0x0D|0x00)
#define ERXWRPTL (0x0E|0x00)
#define ERXWRPTH (0x0F|0x00)
#define EDMASTL (0x10|0x00)
#define EDMASTH (0x11|0x00)
#define EDMANDL (0x12|0x00)
#define EDMANDH (0x13|0x00)
#define EDMADSTL (0x14|0x00)
#define EDMADSTH (0x15|0x00)
#define EDMACSL (0x16|0x00)
#define EDMACSH (0x17|0x00)
// Bank 1 registers
#define EHT0 (0x00|0x20)
#define EHT1 (0x01|0x20)
#define EHT2 (0x02|0x20)
#define EHT3 (0x03|0x20)
#define EHT4 (0x04|0x20)
#define EHT5 (0x05|0x20)
#define EHT6 (0x06|0x20)
#define EHT7 (0x07|0x20)
#define EPMM0 (0x08|0x20)
#define EPMM1 (0x09|0x20)
#define EPMM2 (0x0A|0x20)
#define EPMM3 (0x0B|0x20)
#define EPMM4 (0x0C|0x20)
#define EPMM5 (0x0D|0x20)
#define EPMM6 (0x0E|0x20)
#define EPMM7 (0x0F|0x20)
#define EPMCSL (0x10|0x20)
#define EPMCSH (0x11|0x20)
#define EPMOL (0x14|0x20)
#define EPMOH (0x15|0x20)
#define EWOLIE (0x16|0x20)
#define EWOLIR (0x17|0x20)
#define ERXFCON (0x18|0x20)
#define EPKTCNT (0x19|0x20)
// Bank 2 registers
#define MACON1 (0x00|0x40|0x80)
#define MACON2 (0x01|0x40|0x80)
#define MACON3 (0x02|0x40|0x80)
#define MACON4 (0x03|0x40|0x80)
#define MABBIPG (0x04|0x40|0x80)
#define MAIPGL (0x06|0x40|0x80)
#define MAIPGH (0x07|0x40|0x80)
#define MACLCON1 (0x08|0x40|0x80)
#define MACLCON2 (0x09|0x40|0x80)
#define MAMXFLL (0x0A|0x40|0x80)
#define MAMXFLH (0x0B|0x40|0x80)
#define MAPHSUP (0x0D|0x40|0x80)
#define MICON (0x11|0x40|0x80)
#define MICMD (0x12|0x40|0x80)
#define MIREGADR (0x14|0x40|0x80)
#define MIWRL (0x16|0x40|0x80)
#define MIWRH (0x17|0x40|0x80)
#define MIRDL (0x18|0x40|0x80)
#define MIRDH (0x19|0x40|0x80)
// Bank 3 registers
#define MAADR1 (0x00|0x60|0x80)
#define MAADR0 (0x01|0x60|0x80)
#define MAADR3 (0x02|0x60|0x80)
#define MAADR2 (0x03|0x60|0x80)
#define MAADR5 (0x04|0x60|0x80)
#define MAADR4 (0x05|0x60|0x80)
#define EBSTSD (0x06|0x60)
#define EBSTCON (0x07|0x60)
#define EBSTCSL (0x08|0x60)
#define EBSTCSH (0x09|0x60)
#define MISTAT (0x0A|0x60|0x80)
#define EREVID (0x12|0x60)
#define ECOCON (0x15|0x60)
#define EFLOCON (0x17|0x60)
#define EPAUSL (0x18|0x60)
#define EPAUSH (0x19|0x60)
// PHY registers
#define PHCON1 0x00
#define PHSTAT1 0x01
#define PHHID1 0x02
#define PHHID2 0x03
#define PHCON2 0x10
#define PHSTAT2 0x11
#define PHIE 0x12
#define PHIR 0x13
#define PHLCON 0x14
// ENC28J60 ERXFCON Register Bit Definitions
#define ERXFCON_UCEN 0x80
#define ERXFCON_ANDOR 0x40
#define ERXFCON_CRCEN 0x20
#define ERXFCON_PMEN 0x10
#define ERXFCON_MPEN 0x08
#define ERXFCON_HTEN 0x04
#define ERXFCON_MCEN 0x02
#define ERXFCON_BCEN 0x01
// ENC28J60 EIE Register Bit Definitions
#define EIE_INTIE 0x80
#define EIE_PKTIE 0x40
#define EIE_DMAIE 0x20
#define EIE_LINKIE 0x10
#define EIE_TXIE 0x08
#define EIE_WOLIE 0x04
#define EIE_TXERIE 0x02
#define EIE_RXERIE 0x01
// ENC28J60 EIR Register Bit Definitions
#define EIR_PKTIF 0x40
#define EIR_DMAIF 0x20
#define EIR_LINKIF 0x10
#define EIR_TXIF 0x08
#define EIR_WOLIF 0x04
#define EIR_TXERIF 0x02
#define EIR_RXERIF 0x01
// ENC28J60 ESTAT Register Bit Definitions
#define ESTAT_INT 0x80
#define ESTAT_LATECOL 0x10
#define ESTAT_RXBUSY 0x04
#define ESTAT_TXABRT 0x02
#define ESTAT_CLKRDY 0x01
// ENC28J60 ECON2 Register Bit Definitions
#define ECON2_AUTOINC 0x80
#define ECON2_PKTDEC 0x40
#define ECON2_PWRSV 0x20
#define ECON2_VRPS 0x08
// ENC28J60 ECON1 Register Bit Definitions
#define ECON1_TXRST 0x80
#define ECON1_RXRST 0x40
#define ECON1_DMAST 0x20
#define ECON1_CSUMEN 0x10
#define ECON1_TXRTS 0x08
#define ECON1_RXEN 0x04
#define ECON1_BSEL1 0x02
#define ECON1_BSEL0 0x01
// ENC28J60 MACON1 Register Bit Definitions
#define MACON1_LOOPBK 0x10
#define MACON1_TXPAUS 0x08
#define MACON1_RXPAUS 0x04
#define MACON1_PASSALL 0x02
#define MACON1_MARXEN 0x01
// ENC28J60 MACON2 Register Bit Definitions
#define MACON2_MARST 0x80
#define MACON2_RNDRST 0x40
#define MACON2_MARXRST 0x08
#define MACON2_RFUNRST 0x04
#define MACON2_MATXRST 0x02
#define MACON2_TFUNRST 0x01
// ENC28J60 MACON3 Register Bit Definitions
#define MACON3_PADCFG2 0x80
#define MACON3_PADCFG1 0x40
#define MACON3_PADCFG0 0x20
#define MACON3_TXCRCEN 0x10
#define MACON3_PHDRLEN 0x08
#define MACON3_HFRMLEN 0x04
#define MACON3_FRMLNEN 0x02
#define MACON3_FULDPX 0x01
// ENC28J60 MACON4 Register Bit Definitions
#define MACON4_DEFER (1<<6)
#define MACON4_BPEN (1<<5)
#define MACON4_NOBKOFF (1<<4)
// ENC28J60 MICMD Register Bit Definitions
#define MICMD_MIISCAN 0x02
#define MICMD_MIIRD 0x01
// ENC28J60 MISTAT Register Bit Definitions
#define MISTAT_NVALID 0x04
#define MISTAT_SCAN 0x02
#define MISTAT_BUSY 0x01
// ENC28J60 PHY PHCON1 Register Bit Definitions
#define PHCON1_PRST 0x8000
#define PHCON1_PLOOPBK 0x4000
#define PHCON1_PPWRSV 0x0800
#define PHCON1_PDPXMD 0x0100
// ENC28J60 PHY PHSTAT1 Register Bit Definitions
#define PHSTAT1_PFDPX 0x1000
#define PHSTAT1_PHDPX 0x0800
#define PHSTAT1_LLSTAT 0x0004
#define PHSTAT1_JBSTAT 0x0002
/* ENC28J60 PHY PHSTAT2 Register Bit Definitions */
#define PHSTAT2_TXSTAT (1 << 13)
#define PHSTAT2_RXSTAT (1 << 12)
#define PHSTAT2_COLSTAT (1 << 11)
#define PHSTAT2_LSTAT (1 << 10)
#define PHSTAT2_DPXSTAT (1 << 9)
#define PHSTAT2_PLRITY (1 << 5)
// ENC28J60 PHY PHCON2 Register Bit Definitions
#define PHCON2_FRCLINK 0x4000
#define PHCON2_TXDIS 0x2000
#define PHCON2_JABBER 0x0400
#define PHCON2_HDLDIS 0x0100
// ENC28J60 Packet Control Byte Bit Definitions
#define PKTCTRL_PHUGEEN 0x08
#define PKTCTRL_PPADEN 0x04
#define PKTCTRL_PCRCEN 0x02
#define PKTCTRL_POVERRIDE 0x01
/* ENC28J60 Transmit Status Vector */
#define TSV_TXBYTECNT 0
#define TSV_TXCOLLISIONCNT 16
#define TSV_TXCRCERROR 20
#define TSV_TXLENCHKERROR 21
#define TSV_TXLENOUTOFRANGE 22
#define TSV_TXDONE 23
#define TSV_TXMULTICAST 24
#define TSV_TXBROADCAST 25
#define TSV_TXPACKETDEFER 26
#define TSV_TXEXDEFER 27
#define TSV_TXEXCOLLISION 28
#define TSV_TXLATECOLLISION 29
#define TSV_TXGIANT 30
#define TSV_TXUNDERRUN 31
#define TSV_TOTBYTETXONWIRE 32
#define TSV_TXCONTROLFRAME 48
#define TSV_TXPAUSEFRAME 49
#define TSV_BACKPRESSUREAPP 50
#define TSV_TXVLANTAGFRAME 51
#define TSV_SIZE 7
#define TSV_BYTEOF(x) ((x) / 8)
#define TSV_BITMASK(x) (1 << ((x) % 8))
#define TSV_GETBIT(x, y) (((x)[TSV_BYTEOF(y)] & TSV_BITMASK(y)) ? 1 : 0)
/* ENC28J60 Receive Status Vector */
#define RSV_RXLONGEVDROPEV 16
#define RSV_CARRIEREV 18
#define RSV_CRCERROR 20
#define RSV_LENCHECKERR 21
#define RSV_LENOUTOFRANGE 22
#define RSV_RXOK 23
#define RSV_RXMULTICAST 24
#define RSV_RXBROADCAST 25
#define RSV_DRIBBLENIBBLE 26
#define RSV_RXCONTROLFRAME 27
#define RSV_RXPAUSEFRAME 28
#define RSV_RXUNKNOWNOPCODE 29
#define RSV_RXTYPEVLAN 30
#define RSV_SIZE 6
#define RSV_BITMASK(x) (1 << ((x) - 16))
#define RSV_GETBIT(x, y) (((x) & RSV_BITMASK(y)) ? 1 : 0)
// SPI operation codes
#define ENC28J60_READ_CTRL_REG 0x00
#define ENC28J60_READ_BUF_MEM 0x3A
#define ENC28J60_WRITE_CTRL_REG 0x40
#define ENC28J60_WRITE_BUF_MEM 0x7A
#define ENC28J60_BIT_FIELD_SET 0x80
#define ENC28J60_BIT_FIELD_CLR 0xA0
#define ENC28J60_SOFT_RESET 0xFF
// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata
// buffer boundaries applied to internal 8K ram
// the entire available packet buffer space is allocated
//
// start with recbuf at 0/
#define RXSTART_INIT 0x0
// receive buffer end
#define RXSTOP_INIT (0x1FFF-0x0600) - 1
// start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (~1500 bytes)
#define TXSTART_INIT (0x1FFF-0x0600)
// stp TX buffer at end of mem
#define TXSTOP_INIT 0x1FFF
// max frame length which the conroller will accept:
#define MAX_FRAMELEN 1518
void rt_hw_enc28j60_init(void);
#endif

View File

@ -1,942 +0,0 @@
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name : msd.c
* Author : MCD Application Team
* Version : V2.1
* Date : 05/30/2008
* Description : MSD card driver source file.
* Pin assignment:
* ----------------------------------------------
* | STM32F10x | MSD Pin |
* ----------------------------------------------
* | P0.4 | ChipSelect 1 |
* | P0.1 / MOSI | DataIn 2 |
* | | GND 3 (0 V) |
* | | VDD 4 (3.3 V) |
* | P0.2 / SCLK | Clock 5 |
* | | GND 6 (0 V) |
* | P0.0 / MISO | DataOut 7 |
* -----------------------------------------------
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
* FOR MORE INFORMATION PLEASE CAREFULLY READ THE LICENSE AGREEMENT FILE LOCATED
* IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE.
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "msd.h"
#include <stm32f10x_spi.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Select MSD Card: ChipSelect pin low */
#define MSD_CS_LOW() GPIO_ResetBits(GPIOD, GPIO_Pin_9)
/* Deselect MSD Card: ChipSelect pin high */
#define MSD_CS_HIGH() GPIO_SetBits(GPIOD, GPIO_Pin_9)
#define MSD_SPI SPI1
#define MSD_RCC_SPI RCC_APB2Periph_SPI1
/* Private function prototypes -----------------------------------------------*/
static void SPI_Config(void);
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : MSD_Init
* Description : Initializes the MSD/SD communication.
* Input : None
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_Init(void)
{
u32 i = 0;
/* Initialize SPI */
SPI_Config();
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte 0xFF, 10 times with CS high*/
/* rise CS and MOSI for 80 clocks cycles */
for (i = 0; i <= 9; i++)
{
/* Send dummy byte 0xFF */
MSD_WriteByte(DUMMY);
}
/*------------Put MSD in SPI mode--------------*/
/* MSD initialized and set to SPI mode properly */
return (MSD_GoIdleState());
}
/*******************************************************************************
* Function Name : MSD_WriteBlock
* Description : Writes a block on the MSD
* Input : - pBuffer : pointer to the buffer containing the data to be
* written on the MSD.
* - WriteAddr : address to write on.
* - NumByteToWrite: number of data to write
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD24 (MSD_WRITE_BLOCK) to write multiple block */
MSD_SendCmd(MSD_WRITE_BLOCK, WriteAddr, 0xFF);
/* Check if the MSD acknowledged the write block command: R1 response (0x00: no errors) */
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
/* Send a dummy byte */
MSD_WriteByte(DUMMY);
/* Send the data token to signify the start of the data */
MSD_WriteByte(0xFE);
/* Write the block data to MSD : write count data by block */
for (i = 0; i < NumByteToWrite; i++)
{
/* Send the pointed byte */
MSD_WriteByte(*pBuffer);
/* Point to the next location where the byte read will be saved */
pBuffer++;
}
/* Put CRC bytes (not really needed by us, but required by MSD) */
MSD_ReadByte();
MSD_ReadByte();
/* Read data response */
if (MSD_GetDataResponse() == MSD_DATA_OK)
{
rvalue = MSD_RESPONSE_NO_ERROR;
}
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Returns the reponse */
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_ReadBlock
* Description : Reads a block of data from the MSD.
* Input : - pBuffer : pointer to the buffer that receives the data read
* from the MSD.
* - ReadAddr : MSD's internal address to read from.
* - NumByteToRead : number of bytes to read from the MSD.
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD17 (MSD_READ_SINGLE_BLOCK) to read one block */
MSD_SendCmd(MSD_READ_SINGLE_BLOCK, ReadAddr, 0xFF);
/* Check if the MSD acknowledged the read block command: R1 response (0x00: no errors) */
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
/* Now look for the data token to signify the start of the data */
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
/* Read the MSD block data : read NumByteToRead data */
for (i = 0; i < NumByteToRead; i++)
{
/* Save the received data */
*pBuffer = MSD_ReadByte();
/* Point to the next location where the byte read will be saved */
pBuffer++;
}
/* Get CRC bytes (not really needed by us, but required by MSD) */
MSD_ReadByte();
MSD_ReadByte();
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
}
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Returns the reponse */
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_WriteBuffer
* Description : Writes many blocks on the MSD
* Input : - pBuffer : pointer to the buffer containing the data to be
* written on the MSD.
* - WriteAddr : address to write on.
* - NumByteToWrite: number of data to write
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite)
{
u32 i = 0, NbrOfBlock = 0, Offset = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
/* Calculate number of blocks to write */
NbrOfBlock = NumByteToWrite / BLOCK_SIZE;
/* MSD chip select low */
MSD_CS_LOW();
/* Data transfer */
while (NbrOfBlock --)
{
/* Send CMD24 (MSD_WRITE_BLOCK) to write blocks */
MSD_SendCmd(MSD_WRITE_BLOCK, WriteAddr + Offset, 0xFF);
/* Check if the MSD acknowledged the write block command: R1 response (0x00: no errors) */
if (MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
return MSD_RESPONSE_FAILURE;
}
/* Send dummy byte */
MSD_WriteByte(DUMMY);
/* Send the data token to signify the start of the data */
MSD_WriteByte(MSD_START_DATA_SINGLE_BLOCK_WRITE);
/* Write the block data to MSD : write count data by block */
for (i = 0; i < BLOCK_SIZE; i++)
{
/* Send the pointed byte */
MSD_WriteByte(*pBuffer);
/* Point to the next location where the byte read will be saved */
pBuffer++;
}
/* Set next write address */
Offset += 512;
/* Put CRC bytes (not really needed by us, but required by MSD) */
MSD_ReadByte();
MSD_ReadByte();
/* Read data response */
if (MSD_GetDataResponse() == MSD_DATA_OK)
{
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
}
else
{
/* Set response value to failure */
rvalue = MSD_RESPONSE_FAILURE;
}
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Returns the reponse */
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_ReadBuffer
* Description : Reads multiple block of data from the MSD.
* Input : - pBuffer : pointer to the buffer that receives the data read
* from the MSD.
* - ReadAddr : MSD's internal address to read from.
* - NumByteToRead : number of bytes to read from the MSD.
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead)
{
u32 i = 0, NbrOfBlock = 0, Offset = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
/* Calculate number of blocks to read */
NbrOfBlock = NumByteToRead / BLOCK_SIZE;
/* MSD chip select low */
MSD_CS_LOW();
/* Data transfer */
while (NbrOfBlock --)
{
/* Send CMD17 (MSD_READ_SINGLE_BLOCK) to read one block */
MSD_SendCmd (MSD_READ_SINGLE_BLOCK, ReadAddr + Offset, 0xFF);
/* Check if the MSD acknowledged the read block command: R1 response (0x00: no errors) */
if (MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
return MSD_RESPONSE_FAILURE;
}
/* Now look for the data token to signify the start of the data */
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
/* Read the MSD block data : read NumByteToRead data */
for (i = 0; i < BLOCK_SIZE; i++)
{
/* Read the pointed data */
*pBuffer = MSD_ReadByte();
/* Point to the next location where the byte read will be saved */
pBuffer++;
}
/* Set next read address*/
Offset += 512;
/* get CRC bytes (not really needed by us, but required by MSD) */
MSD_ReadByte();
MSD_ReadByte();
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
}
else
{
/* Set response value to failure */
rvalue = MSD_RESPONSE_FAILURE;
}
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Returns the reponse */
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_GetCSDRegister
* Description : Read the CSD card register.
* Reading the contents of the CSD register in SPI mode
* is a simple read-block transaction.
* Input : - MSD_csd: pointer on an SCD register structure
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GetCSDRegister(sMSD_CSD* MSD_csd)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
u8 CSD_Tab[16];
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD9 (CSD register) or CMD10(CSD register) */
MSD_SendCmd(MSD_SEND_CSD, 0, 0xFF);
/* Wait for response in the R1 format (0x00 is no errors) */
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
for (i = 0; i < 16; i++)
{
/* Store CSD register value on CSD_Tab */
CSD_Tab[i] = MSD_ReadByte();
}
}
/* Get CRC bytes (not really needed by us, but required by MSD) */
MSD_WriteByte(DUMMY);
MSD_WriteByte(DUMMY);
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Byte 0 */
MSD_csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6;
MSD_csd->SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2;
MSD_csd->Reserved1 = CSD_Tab[0] & 0x03;
/* Byte 1 */
MSD_csd->TAAC = CSD_Tab[1] ;
/* Byte 2 */
MSD_csd->NSAC = CSD_Tab[2];
/* Byte 3 */
MSD_csd->MaxBusClkFrec = CSD_Tab[3];
/* Byte 4 */
MSD_csd->CardComdClasses = CSD_Tab[4] << 4;
/* Byte 5 */
MSD_csd->CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4;
MSD_csd->RdBlockLen = CSD_Tab[5] & 0x0F;
/* Byte 6 */
MSD_csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7;
MSD_csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6;
MSD_csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5;
MSD_csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4;
MSD_csd->Reserved2 = 0; /* Reserved */
MSD_csd->DeviceSize = (CSD_Tab[6] & 0x03) << 10;
/* Byte 7 */
MSD_csd->DeviceSize |= (CSD_Tab[7]) << 2;
/* Byte 8 */
MSD_csd->DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6;
MSD_csd->MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3;
MSD_csd->MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07);
/* Byte 9 */
MSD_csd->MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5;
MSD_csd->MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2;
MSD_csd->DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1;
/* Byte 10 */
MSD_csd->DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7;
MSD_csd->EraseGrSize = (CSD_Tab[10] & 0x7C) >> 2;
MSD_csd->EraseGrMul = (CSD_Tab[10] & 0x03) << 3;
/* Byte 11 */
MSD_csd->EraseGrMul |= (CSD_Tab[11] & 0xE0) >> 5;
MSD_csd->WrProtectGrSize = (CSD_Tab[11] & 0x1F);
/* Byte 12 */
MSD_csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7;
MSD_csd->ManDeflECC = (CSD_Tab[12] & 0x60) >> 5;
MSD_csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2;
MSD_csd->MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2;
/* Byte 13 */
MSD_csd->MaxWrBlockLen |= (CSD_Tab[13] & 0xc0) >> 6;
MSD_csd->WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5;
MSD_csd->Reserved3 = 0;
MSD_csd->ContentProtectAppli = (CSD_Tab[13] & 0x01);
/* Byte 14 */
MSD_csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7;
MSD_csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6;
MSD_csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5;
MSD_csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4;
MSD_csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2;
MSD_csd->ECC = (CSD_Tab[14] & 0x03);
/* Byte 15 */
MSD_csd->msd_CRC = (CSD_Tab[15] & 0xFE) >> 1;
MSD_csd->Reserved4 = 1;
/* Return the reponse */
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_GetCIDRegister
* Description : Read the CID card register.
* Reading the contents of the CID register in SPI mode
* is a simple read-block transaction.
* Input : - MSD_cid: pointer on an CID register structure
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GetCIDRegister(sMSD_CID* MSD_cid)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
u8 CID_Tab[16];
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD10 (CID register) */
MSD_SendCmd(MSD_SEND_CID, 0, 0xFF);
/* Wait for response in the R1 format (0x00 is no errors) */
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
/* Store CID register value on CID_Tab */
for (i = 0; i < 16; i++)
{
CID_Tab[i] = MSD_ReadByte();
}
}
/* Get CRC bytes (not really needed by us, but required by MSD) */
MSD_WriteByte(DUMMY);
MSD_WriteByte(DUMMY);
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Byte 0 */
MSD_cid->ManufacturerID = CID_Tab[0];
/* Byte 1 */
MSD_cid->OEM_AppliID = CID_Tab[1] << 8;
/* Byte 2 */
MSD_cid->OEM_AppliID |= CID_Tab[2];
/* Byte 3 */
MSD_cid->ProdName1 = CID_Tab[3] << 24;
/* Byte 4 */
MSD_cid->ProdName1 |= CID_Tab[4] << 16;
/* Byte 5 */
MSD_cid->ProdName1 |= CID_Tab[5] << 8;
/* Byte 6 */
MSD_cid->ProdName1 |= CID_Tab[6];
/* Byte 7 */
MSD_cid->ProdName2 = CID_Tab[7];
/* Byte 8 */
MSD_cid->ProdRev = CID_Tab[8];
/* Byte 9 */
MSD_cid->ProdSN = CID_Tab[9] << 24;
/* Byte 10 */
MSD_cid->ProdSN |= CID_Tab[10] << 16;
/* Byte 11 */
MSD_cid->ProdSN |= CID_Tab[11] << 8;
/* Byte 12 */
MSD_cid->ProdSN |= CID_Tab[12];
/* Byte 13 */
MSD_cid->Reserved1 |= (CID_Tab[13] & 0xF0) >> 4;
/* Byte 14 */
MSD_cid->ManufactDate = (CID_Tab[13] & 0x0F) << 8;
/* Byte 15 */
MSD_cid->ManufactDate |= CID_Tab[14];
/* Byte 16 */
MSD_cid->msd_CRC = (CID_Tab[15] & 0xFE) >> 1;
MSD_cid->Reserved2 = 1;
/* Return the reponse */
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_SendCmd
* Description : Send 5 bytes command to the MSD card.
* Input : - Cmd: the user expected command to send to MSD card
* - Arg: the command argument
* - Crc: the CRC
* Output : None
* Return : None
*******************************************************************************/
void MSD_SendCmd(u8 Cmd, u32 Arg, u8 Crc)
{
u32 i = 0x00;
u8 Frame[6];
/* Construct byte1 */
Frame[0] = (Cmd | 0x40);
/* Construct byte2 */
Frame[1] = (u8)(Arg >> 24);
/* Construct byte3 */
Frame[2] = (u8)(Arg >> 16);
/* Construct byte4 */
Frame[3] = (u8)(Arg >> 8);
/* Construct byte5 */
Frame[4] = (u8)(Arg);
/* Construct CRC: byte6 */
Frame[5] = (Crc);
/* Send the Cmd bytes */
for (i = 0; i < 6; i++)
{
MSD_WriteByte(Frame[i]);
}
}
/*******************************************************************************
* Function Name : MSD_GetDataResponse
* Description : Get MSD card data response.
* Input : None
* Output : None
* Return : The MSD status: Read data response xxx0<status>1
* - status 010: Data accecpted
* - status 101: Data rejected due to a crc error
* - status 110: Data rejected due to a Write error.
* - status 111: Data rejected due to other error.
*******************************************************************************/
u8 MSD_GetDataResponse(void)
{
u32 i = 0;
u8 response, rvalue;
while (i <= 64)
{
/* Read resonse */
response = MSD_ReadByte();
/* Mask unused bits */
response &= 0x1F;
switch (response)
{
case MSD_DATA_OK:
{
rvalue = MSD_DATA_OK;
break;
}
case MSD_DATA_CRC_ERROR:
return MSD_DATA_CRC_ERROR;
case MSD_DATA_WRITE_ERROR:
return MSD_DATA_WRITE_ERROR;
default:
{
rvalue = MSD_DATA_OTHER_ERROR;
break;
}
}
/* Exit loop in case of data ok */
if (rvalue == MSD_DATA_OK)
break;
/* Increment loop counter */
i++;
}
/* Wait null data */
while (MSD_ReadByte() == 0);
/* Return response */
return response;
}
/*******************************************************************************
* Function Name : MSD_GetResponse
* Description : Returns the MSD response.
* Input : None
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GetResponse(u8 Response)
{
u32 Count = 0xFFF;
/* Check if response is got or a timeout is happen */
while ((MSD_ReadByte() != Response) && Count)
{
Count--;
}
if (Count == 0)
{
/* After time out */
return MSD_RESPONSE_FAILURE;
}
else
{
/* Right response got */
return MSD_RESPONSE_NO_ERROR;
}
}
/*******************************************************************************
* Function Name : MSD_GetStatus
* Description : Returns the MSD status.
* Input : None
* Output : None
* Return : The MSD status.
*******************************************************************************/
u16 MSD_GetStatus(void)
{
u16 Status = 0;
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD13 (MSD_SEND_STATUS) to get MSD status */
MSD_SendCmd(MSD_SEND_STATUS, 0, 0xFF);
Status = MSD_ReadByte();
Status |= (u16)(MSD_ReadByte() << 8);
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte 0xFF */
MSD_WriteByte(DUMMY);
return Status;
}
/*******************************************************************************
* Function Name : MSD_GoIdleState
* Description : Put MSD in Idle state.
* Input : None
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GoIdleState(void)
{
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD0 (GO_IDLE_STATE) to put MSD in SPI mode */
MSD_SendCmd(MSD_GO_IDLE_STATE, 0, 0x95);
/* Wait for In Idle State Response (R1 Format) equal to 0x01 */
if (MSD_GetResponse(MSD_IN_IDLE_STATE))
{
/* No Idle State Response: return response failue */
return MSD_RESPONSE_FAILURE;
}
/*----------Activates the card initialization process-----------*/
do
{
/* MSD chip select high */
MSD_CS_HIGH();
/* Send Dummy byte 0xFF */
MSD_WriteByte(DUMMY);
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD1 (Activates the card process) until response equal to 0x0 */
MSD_SendCmd(MSD_SEND_OP_COND, 0, 0xFF);
/* Wait for no error Response (R1 Format) equal to 0x00 */
}
while (MSD_GetResponse(MSD_RESPONSE_NO_ERROR));
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte 0xFF */
MSD_WriteByte(DUMMY);
return MSD_RESPONSE_NO_ERROR;
}
/*******************************************************************************
* Function Name : MSD_WriteByte
* Description : Write a byte on the MSD.
* Input : Data: byte to send.
* Output : None
* Return : None.
*******************************************************************************/
void MSD_WriteByte(u8 Data)
{
/* Wait until the transmit buffer is empty */
while (SPI_I2S_GetFlagStatus(MSD_SPI, SPI_I2S_FLAG_TXE) == RESET);
/* Send the byte */
SPI_I2S_SendData(MSD_SPI, Data);
/*!< Wait to receive a byte*/
while(SPI_I2S_GetFlagStatus(MSD_SPI, SPI_I2S_FLAG_RXNE) == RESET);
/*!< Return the byte read from the SPI bus */
SPI_I2S_ReceiveData(MSD_SPI);
}
/*******************************************************************************
* Function Name : MSD_ReadByte
* Description : Read a byte from the MSD.
* Input : None.
* Output : None
* Return : The received byte.
*******************************************************************************/
u8 MSD_ReadByte(void)
{
u8 Data = 0;
/* Wait until the transmit buffer is empty */
while (SPI_I2S_GetFlagStatus(MSD_SPI, SPI_I2S_FLAG_TXE) == RESET);
/* Send the byte */
SPI_I2S_SendData(MSD_SPI, DUMMY);
/* Wait until a data is received */
while (SPI_I2S_GetFlagStatus(MSD_SPI, SPI_I2S_FLAG_RXNE) == RESET);
/* Get the received data */
Data = SPI_I2S_ReceiveData(MSD_SPI);
/* Return the shifted data */
return Data;
}
/*******************************************************************************
* Function Name : SPI_Config
* Description : Initializes the SPI and CS pins.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SPI_Config(void)
{
uint32_t delay;
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
/* GPIOA and GPIOC Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);
/* SPI Periph clock enable */
RCC_APB2PeriphClockCmd(MSD_RCC_SPI, ENABLE);
/* Configure SPI pins: SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure PD9 pin: CS pin ,PD10 : SD Power */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* SPI Config */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(MSD_SPI, &SPI_InitStructure);
/* SPI enable */
SPI_Cmd(MSD_SPI, ENABLE);
/* active SD card */
GPIO_ResetBits(GPIOD, GPIO_Pin_10);
for (delay = 0; delay < 0xfffff; delay ++);
}
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
/*
* RT-Thread SD Card Driver
* 2009-04-17 Bernard first version
* 2010-07-15 Modify read/write according new block driver interface
*/
#include <rtthread.h>
#include <dfs_fs.h>
static struct rt_device sdcard_device;
static struct dfs_partition part;
#define SECTOR_SIZE 512
/* RT-Thread Device Driver Interface */
static rt_err_t rt_msd_init(rt_device_t dev)
{
sMSD_CSD MSD_csd;
MSD_GetCSDRegister(&MSD_csd);
return RT_EOK;
}
static rt_err_t rt_msd_open(rt_device_t dev, rt_uint16_t oflag)
{
return RT_EOK;
}
static rt_err_t rt_msd_close(rt_device_t dev)
{
return RT_EOK;
}
static rt_size_t rt_msd_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
rt_uint8_t status;
rt_uint32_t i;
status = MSD_RESPONSE_NO_ERROR;
// rt_kprintf("read: 0x%x, size %d\n", pos, size);
/* read all sectors */
for (i = 0; i < size; i ++)
{
status = MSD_ReadBlock((rt_uint8_t*)((rt_uint8_t*)buffer + i * SECTOR_SIZE),
(part.offset + pos + i)* SECTOR_SIZE, SECTOR_SIZE);
if (status != MSD_RESPONSE_NO_ERROR)
{
rt_kprintf("sd card read failed\n");
return 0;
}
}
if (status == MSD_RESPONSE_NO_ERROR) return size;
rt_kprintf("read failed: %d\n", status);
return 0;
}
static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
rt_uint8_t status;
rt_uint32_t i;
status = MSD_RESPONSE_NO_ERROR;
// rt_kprintf("write: 0x%x, size %d\n", pos, size);
/* write all sectors */
for (i = 0; i < size; i ++)
{
status = MSD_WriteBuffer((rt_uint8_t*)((rt_uint8_t*)buffer + i * SECTOR_SIZE),
(part.offset + pos + i)* SECTOR_SIZE, SECTOR_SIZE);
if (status != MSD_RESPONSE_NO_ERROR)
{
rt_kprintf("sd card write failed\n");
return 0;
}
}
if (status == MSD_RESPONSE_NO_ERROR) return size;
rt_kprintf("write failed: %d\n", status);
return 0;
}
static rt_err_t rt_msd_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
RT_ASSERT(dev != RT_NULL);
return RT_EOK;
}
void rt_hw_msd_init()
{
if (MSD_Init() == MSD_RESPONSE_NO_ERROR)
{
rt_uint8_t status;
rt_uint8_t *sector;
/* register sdcard device */
sdcard_device.init = rt_msd_init;
sdcard_device.open = rt_msd_open;
sdcard_device.close = rt_msd_close;
sdcard_device.read = rt_msd_read;
sdcard_device.write = rt_msd_write;
sdcard_device.control = rt_msd_control;
/* no private */
sdcard_device.user_data = RT_NULL;
/* get the first sector to read partition table */
sector = (rt_uint8_t*) rt_malloc (512);
if (sector == RT_NULL)
{
rt_kprintf("allocate partition sector buffer failed\n");
return;
}
status = MSD_ReadBlock(sector, 0, 512);
if (status == MSD_RESPONSE_NO_ERROR)
{
/* get the first partition */
status = dfs_filesystem_get_partition(&part, sector, 0);
if (status != RT_EOK)
{
/* there is no partition table */
part.offset = 0;
part.size = 0;
}
}
else
{
/* there is no partition table */
part.offset = 0;
part.size = 0;
}
/* release sector buffer */
rt_free(sector);
rt_device_register(&sdcard_device, "sd0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
}
else
{
rt_kprintf("sdcard init failed\n");
}
}

View File

@ -1,173 +0,0 @@
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name : msd.h
* Author : MCD Application Team
* Version : V2.1
* Date : 05/30/2008
* Description : Header for msd.c file.
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
* FOR MORE INFORMATION PLEASE CAREFULLY READ THE LICENSE AGREEMENT FILE LOCATED
* IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE.
*******************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MSD_H
#define __MSD_H
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Private define ------------------------------------------------------------*/
/* Block Size */
#define BLOCK_SIZE 512
/* Dummy byte */
#define DUMMY 0xFF
/* Start Data tokens */
/* Tokens (necessary because at nop/idle (and CS active) only 0xff is on the data/command line) */
#define MSD_START_DATA_SINGLE_BLOCK_READ 0xFE /* Data token start byte, Start Single Block Read */
#define MSD_START_DATA_MULTIPLE_BLOCK_READ 0xFE /* Data token start byte, Start Multiple Block Read */
#define MSD_START_DATA_SINGLE_BLOCK_WRITE 0xFE /* Data token start byte, Start Single Block Write */
#define MSD_START_DATA_MULTIPLE_BLOCK_WRITE 0xFD /* Data token start byte, Start Multiple Block Write */
#define MSD_STOP_DATA_MULTIPLE_BLOCK_WRITE 0xFD /* Data toke stop byte, Stop Multiple Block Write */
/* MSD functions return */
#define MSD_SUCCESS 0x00
#define MSD_FAIL 0xFF
/* MSD reponses and error flags */
#define MSD_RESPONSE_NO_ERROR 0x00
#define MSD_IN_IDLE_STATE 0x01
#define MSD_ERASE_RESET 0x02
#define MSD_ILLEGAL_COMMAND 0x04
#define MSD_COM_CRC_ERROR 0x08
#define MSD_ERASE_SEQUENCE_ERROR 0x10
#define MSD_ADDRESS_ERROR 0x20
#define MSD_PARAMETER_ERROR 0x40
#define MSD_RESPONSE_FAILURE 0xFF
/* Data response error */
#define MSD_DATA_OK 0x05
#define MSD_DATA_CRC_ERROR 0x0B
#define MSD_DATA_WRITE_ERROR 0x0D
#define MSD_DATA_OTHER_ERROR 0xFF
/* Commands: CMDxx = CMD-number | 0x40 */
#define MSD_GO_IDLE_STATE 0 /* CMD0=0x40 */
#define MSD_SEND_OP_COND 1 /* CMD1=0x41 */
#define MSD_SEND_CSD 9 /* CMD9=0x49 */
#define MSD_SEND_CID 10 /* CMD10=0x4A */
#define MSD_STOP_TRANSMISSION 12 /* CMD12=0x4C */
#define MSD_SEND_STATUS 13 /* CMD13=0x4D */
#define MSD_SET_BLOCKLEN 16 /* CMD16=0x50 */
#define MSD_READ_SINGLE_BLOCK 17 /* CMD17=0x51 */
#define MSD_READ_MULTIPLE_BLOCK 18 /* CMD18=0x52 */
#define MSD_SET_BLOCK_COUNT 23 /* CMD23=0x57 */
#define MSD_WRITE_BLOCK 24 /* CMD24=0x58 */
#define MSD_WRITE_MULTIPLE_BLOCK 25 /* CMD25=0x59 */
#define MSD_PROGRAM_CSD 27 /* CMD27=0x5B */
#define MSD_SET_WRITE_PROT 28 /* CMD28=0x5C */
#define MSD_CLR_WRITE_PROT 29 /* CMD29=0x5D */
#define MSD_SEND_WRITE_PROT 30 /* CMD30=0x5E */
#define MSD_TAG_SECTOR_START 32 /* CMD32=0x60 */
#define MSD_TAG_SECTOR_END 33 /* CMD33=0x61 */
#define MSD_UNTAG_SECTOR 34 /* CMD34=0x62 */
#define MSD_TAG_ERASE_GROUP_START 35 /* CMD35=0x63 */
#define MSD_TAG_ERASE_GROUP_END 36 /* CMD36=0x64 */
#define MSD_UNTAG_ERASE_GROUP 37 /* CMD37=0x65 */
#define MSD_ERASE 38 /* CMD38=0x66 */
#define MSD_READ_OCR 39 /* CMD39=0x67 */
#define MSD_CRC_ON_OFF 40 /* CMD40=0x68 */
/* Exported types ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
typedef struct _MSD_CSD /*Card Specific Data*/
{
vu8 CSDStruct; /* CSD structure */
vu8 SysSpecVersion; /* System specification version */
vu8 Reserved1; /* Reserved */
vu8 TAAC; /* Data read access-time 1 */
vu8 NSAC; /* Data read access-time 2 in CLK cycles */
vu8 MaxBusClkFrec; /* Max. bus clock frequency */
vu16 CardComdClasses; /* Card command classes */
vu8 RdBlockLen; /* Max. read data block length */
vu8 PartBlockRead; /* Partial blocks for read allowed */
vu8 WrBlockMisalign; /* Write block misalignment */
vu8 RdBlockMisalign; /* Read block misalignment */
vu8 DSRImpl; /* DSR implemented */
vu8 Reserved2; /* Reserved */
vu16 DeviceSize; /* Device Size */
vu8 MaxRdCurrentVDDMin; /* Max. read current @ VDD min */
vu8 MaxRdCurrentVDDMax; /* Max. read current @ VDD max */
vu8 MaxWrCurrentVDDMin; /* Max. write current @ VDD min */
vu8 MaxWrCurrentVDDMax; /* Max. write current @ VDD max */
vu8 DeviceSizeMul; /* Device size multiplier */
vu8 EraseGrSize; /* Erase group size */
vu8 EraseGrMul; /* Erase group size multiplier */
vu8 WrProtectGrSize; /* Write protect group size */
vu8 WrProtectGrEnable; /* Write protect group enable */
vu8 ManDeflECC; /* Manufacturer default ECC */
vu8 WrSpeedFact; /* Write speed factor */
vu8 MaxWrBlockLen; /* Max. write data block length */
vu8 WriteBlockPaPartial; /* Partial blocks for write allowed */
vu8 Reserved3; /* Reserded */
vu8 ContentProtectAppli; /* Content protection application */
vu8 FileFormatGrouop; /* File format group */
vu8 CopyFlag; /* Copy flag (OTP) */
vu8 PermWrProtect; /* Permanent write protection */
vu8 TempWrProtect; /* Temporary write protection */
vu8 FileFormat; /* File Format */
vu8 ECC; /* ECC code */
vu8 msd_CRC; /* CRC */
vu8 Reserved4; /* always 1*/
}
sMSD_CSD;
typedef struct _MSD_CID /*Card Identification Data*/
{
vu8 ManufacturerID; /* ManufacturerID */
vu16 OEM_AppliID; /* OEM/Application ID */
vu32 ProdName1; /* Product Name part1 */
vu8 ProdName2; /* Product Name part2*/
vu8 ProdRev; /* Product Revision */
vu32 ProdSN; /* Product Serial Number */
vu8 Reserved1; /* Reserved1 */
vu16 ManufactDate; /* Manufacturing Date */
vu8 msd_CRC; /* CRC */
vu8 Reserved2; /* always 1*/
}
sMSD_CID;
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*----- High layer function -----*/
u8 MSD_Init(void);
u8 MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);
u8 MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead);
u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite);
u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead);
u8 MSD_GetCSDRegister(sMSD_CSD* MSD_csd);
u8 MSD_GetCIDRegister(sMSD_CID* MSD_cid);
/*----- Medium layer function -----*/
void MSD_SendCmd(u8 Cmd, u32 Arg, u8 Crc);
u8 MSD_GetResponse(u8 Response);
u8 MSD_GetDataResponse(void);
u8 MSD_GoIdleState(void);
u16 MSD_GetStatus(void);
/*----- Low layer function -----*/
void MSD_WriteByte(u8 byte);
u8 MSD_ReadByte(void);
#endif /* __MSD_H */
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/