diff --git a/bin/functions b/bin/functions --- a/bin/functions +++ b/bin/functions @@ -46,6 +46,37 @@ function Target { fi } + +function Objdir { + if [ -z "$2" ] ; then + OBJDIR=`more $1 | grep -i "OBJDIR " | sed s/OBJDIR// | sed s/=// | sed 's/^[ \t]*//;s/[ \t]*$//'` + if [ -z "$OBJDIR" ] ; then + OBJDIR="obj" + fi + else + OBJDIR=`more $1 | grep -i "$2.OBJDIR " | sed s/$2'\.'OBJDIR// | sed s/=// | sed 's/^[ \t]*//;s/[ \t]*$//'` + if [ -z "$OBJDIR" ] ; then + OBJDIR="obj" + fi + fi +} + + +function Bindir { + if [ -z "$2" ] ; then + BINDIR=`more $1 | grep -i "BINDIR " | sed s/BINDIR// | sed s/=// | sed 's/^[ \t]*//;s/[ \t]*$//'` + if [ -z "$BINDIR" ] ; then + BINDIR="bin" + fi + else + BINDIR=`more $1 | grep -i "$2.OBJDIR " | sed s/$2'\.'BINDIR// | sed s/=// | sed 's/^[ \t]*//;s/[ \t]*$//'` + if [ -z "$BINDIR" ] ; then + BINDIR="bin" + fi + fi +} + + function Targets { TARGETS=`more $1 | grep -i ".SOURCES" | sed 's/\.SOURCES.*//'` } @@ -56,12 +87,14 @@ function Libs_Inc { for FILES in $INCLUDEStmp do INCLUDES+='$('"LIBUC_INC_DIR_""$FILES""_CMD) " + INC_LIBS_DEPS+='$('"LIBUC_INC_DIR_""$FILES"") " done else INCLUDEStmp=`more $1 | grep -i "$2.LIBS " | sed s/$2'\.'LIBS// |sed s/+//|sed s/=//| sed 's/^[ \t]*//;s/[ \t]*$//'` for FILES in $INCLUDEStmp do INCLUDES+='$('"LIBUC_INC_DIR_""$FILES""_CMD) " + INC_LIBS_DEPS+='$('"LIBUC_INC_DIR_""$FILES"") " done fi @@ -73,12 +106,14 @@ function Libs_Link { for FILES in $LIBRARIEStmp do LIBRARIES+='$('"LIBUC_LIBS_DIR_""$FILES""_CMD) "'$('"LIBUC_LIBS_$FILES) " + BIN_LIBS_DEPS='$('"LIBUC_LIBS_DIR_""$FILES"")" done else LIBRARIEStmp=`more $1 | grep -i "$2.LIBS " | sed s/$2'\.'LIBS// |sed s/+//|sed s/=//| sed 's/^[ \t]*//;s/[ \t]*$//'` for FILES in $LIBRARIEStmp do LIBRARIES+='$('"LIBUC_LIBS_DIR_""$FILES""_CMD) "'$('"LIBUC_LIBS_$FILES) " + BIN_LIBS_DEPS='$('"LIBUC_LIBS_DIR_""$FILES"")" done fi diff --git a/bin/templates/libucmake-app b/bin/templates/libucmake-app --- a/bin/templates/libucmake-app +++ b/bin/templates/libucmake-app @@ -20,6 +20,10 @@ #-- Author : Alexis Jeandet #-- Mail : alexis.jeandet@gmail.com #-------------------------------------------------------------------------------*/ +OBJDIR="obj" +BINDIR="bin" +INC_LIBS_DEPS="" +BIN_LIBS_DEPS="" function template-run { Targets $PROJECTFILE @@ -27,6 +31,8 @@ function template-run { echo "Single Target" Target $PROJECTFILE Arch $PROJECTFILE + Objdir $PROJECTFILE + Bindir $PROJECTFILE Libs_Inc $PROJECTFILE Libs_Link $PROJECTFILE HeadersInstallPath $PROJECTFILE @@ -47,7 +53,10 @@ function template-run { echo "=========================================================================" echo "" echo " Start Writing Makefile ..." + echo "OBJDIR = $OBJDIR" >> Makefile + echo "BINDIR = $BINDIR" >> Makefile echo 'OBJECTFILES = $(APPSOURCES:.c=.o)'>> Makefile + echo 'OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES))'>> Makefile echo "ARCH = $ARCH" >> Makefile echo "ARCHFOLDER = "'$(LIBUC)'"/rules/$ARCH" >> Makefile echo "TARGET=$TARGET">> Makefile @@ -67,14 +76,14 @@ function template-run { echo "" else echo "Multi targets" - echo "" >> Makefile - echo "all:" >> Makefile for ITEMS in $TARGETS do echo 'PROJECTDIR = `pwd`'> $ITEMS.mk echo "LIBUC = $libuc2" >> $ITEMS.mk Target $PROJECTFILE $ITEMS Arch $PROJECTFILE $ITEMS + Objdir $PROJECTFILE $ITEMS + Bindir $PROJECTFILE $ITEMS Libs_Inc $PROJECTFILE $ITEMS Libs_Link $PROJECTFILE $ITEMS HeadersInstallPath $PROJECTFILE $ITEMS @@ -95,7 +104,10 @@ function template-run { echo "=========================================================================" echo "" echo " Start Writing Makefile ..." - echo 'OBJECTFILES = $(APPSOURCES:.c=.o)'>> $ITEMS.mk + echo "OBJDIR = $OBJDIR" >> $ITEMS.mk + echo "BINDIR = $BINDIR" >> $ITEMS.mk + echo 'OBJECTFILES = $(APPSOURCES:.c=.o)'>> $ITEMS.mk + echo 'OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES))'>> $ITEMS.mk echo "ARCH = $ARCH" >> $ITEMS.mk echo "ARCHFOLDER = "'$(LIBUC)'"/rules/$ARCH" >> $ITEMS.mk echo "TARGET=$TARGET">> $ITEMS.mk @@ -113,8 +125,19 @@ function template-run { echo "" echo "=========================================================================" echo "" + done + echo "" >> Makefile + echo "all:" >> Makefile + for ITEMS in $TARGETS + do echo " make -f $ITEMS.mk" >> Makefile done + echo "" >> Makefile + echo "clean:" >> Makefile + for ITEMS in $TARGETS + do + echo " make clean -f $ITEMS.mk" >> Makefile + done fi } diff --git a/bin/templates/libucmake-lib b/bin/templates/libucmake-lib --- a/bin/templates/libucmake-lib +++ b/bin/templates/libucmake-lib @@ -27,6 +27,8 @@ function template-run { echo "Single Target" Target $PROJECTFILE Arch $PROJECTFILE + Objdir $PROJECTFILE + Bindir $PROJECTFILE Libs_Inc $PROJECTFILE Libs_Link $PROJECTFILE HeadersInstallPath $PROJECTFILE @@ -46,7 +48,10 @@ function template-run { echo "=========================================================================" echo "" echo " Start Writing Makefile ..." + echo "OBJDIR = $OBJDIR" >> Makefile + echo "BINDIR = $BINDIR" >> Makefile echo 'OBJECTFILES = $(LIBSOURCES:.c=.o)'>> Makefile + echo 'OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES))'>> Makefile echo "ARCH = $ARCH" >> Makefile echo "ARCHFOLDER = "'$(LIBUC)'"/rules/$ARCH" >> Makefile echo "TARGET=$TARGET">> Makefile @@ -59,6 +64,13 @@ function template-run { echo '' >> Makefile echo 'all:lib' >> Makefile echo " @echo Code compiled" >> Makefile + echo '' >> Makefile + echo 'clean:' >> Makefile + echo ' rm -f $(OBJDIR)/*.o' >> Makefile + echo ' rm -f $(TARGETINSTALLPATH)/*.a' >> Makefile + echo ' rm -f $(HEADERSINSTALLPATH)/*.h' >> Makefile + echo ' rm -f $(DEVSOURCESND)' >> Makefile + echo ' rm -f *.d' >> Makefile echo " Makefile writing finished" echo "" echo "=========================================================================" @@ -66,14 +78,14 @@ function template-run { else echo "Multi targets" - echo "" >> Makefile - echo "all:" >> Makefile for ITEMS in $TARGETS do echo 'PROJECTDIR = `pwd`'> $ITEMS.mk echo "LIBUC = $libuc2" >> $ITEMS.mk Target $PROJECTFILE $ITEMS Arch $PROJECTFILE $ITEMS + Objdir $PROJECTFILE + Bindir $PROJECTFILE Libs_Inc $PROJECTFILE $ITEMS Libs_Link $PROJECTFILE $ITEMS HeadersInstallPath $PROJECTFILE $ITEMS @@ -93,7 +105,10 @@ function template-run { echo "=========================================================================" echo "" echo " Start Writing Makefile ..." + echo "OBJDIR = $OBJDIR" >> $ITEMS.mk + echo "BINDIR = $BINDIR" >> $ITEMS.mk echo 'OBJECTFILES = $(LIBSOURCES:.c=.o)'>> $ITEMS.mk + echo 'OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES))'>> $ITEMS.mk echo "ARCH = $ARCH" >> $ITEMS.mk echo "ARCHFOLDER = "'$(LIBUC)'"/rules/$ARCH" >> $ITEMS.mk echo "TARGET=$TARGET">> $ITEMS.mk @@ -106,12 +121,30 @@ function template-run { echo '' >> $ITEMS.mk echo 'all:lib' >> $ITEMS.mk echo " @echo Code compiled" >> $ITEMS.mk + echo '' >> $ITEMS.mk + echo 'clean:' >> $ITEMS.mk + echo ' rm -f $(OBJDIR)/*.o' >> $ITEMS.mk + echo ' rm -f $(TARGETINSTALLPATH)/*.a' >> $ITEMS.mk + echo ' rm -f $(HEADERSINSTALLPATH)/*.h' >> $ITEMS.mk + echo ' rm -f $(DEVSOURCESND)' >> $ITEMS.mk + echo ' rm -f *.d' >> $ITEMS.mk echo " Makefile writing finished" echo "" echo "=========================================================================" echo "" + done + echo "" >> Makefile + echo "all:" >> Makefile + for ITEMS in $TARGETS + do echo " make -f $ITEMS.mk" >> Makefile done + echo "" >> Makefile + echo "clean:" >> Makefile + for ITEMS in $TARGETS + do + echo " make clean -f $ITEMS.mk" >> Makefile + done fi diff --git a/bsp/includes/MP3PlayerV1/bsp.h b/bsp/includes/MP3PlayerV1/bsp.h new file mode 100644 --- /dev/null +++ b/bsp/includes/MP3PlayerV1/bsp.h @@ -0,0 +1,101 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef BSP_H +#define BSP_H +#include "LPC23xx.h" +#include + + +extern uartDev* UART0; +extern uartDev* UART1; +extern uartDev* UART2; +extern uartDev* UART3; + +/*extern i2cDev* IIC0; +extern i2cDev* IIC1; +extern i2cDev* IIC2; + +extern sspDev* SSP0; +extern sspDev* SSP1; + +extern eeprom24lc0xDev eeprom0;*/ + +extern float VREF0; + +extern unsigned int currentCpuFreq; + +#define pll0useInternal 0 +#define pll0useMainOsc 1 +#define pll0useRTC 2 + + +#define pll0setClksrc(src) if((unsigned int)(src)<3) CLKSRCSEL=(src) +#define pll0getClksrc (CLKSRCSEL & 3) + +#define LEDS_ON + +#define LED1_ON +#define LED2_ON +#define LED3_ON +#define LED4_ON +#define LED5_ON +#define LED6_ON +#define LED7_ON +#define LED8_ON + +#define LEDS_OFF + +#define LED1_OFF +#define LED2_OFF +#define LED3_OFF +#define LED4_OFF +#define LED5_OFF +#define LED6_OFF +#define LED7_OFF +#define LED8_OFF + +extern int bsp_init(); + +extern void bsp_GPIO_init(); +extern void bsp_uart_init(); +extern void bsp_iic_init(); +extern void bsp_ssp_init(); +extern void consoleputc(char); +extern char consolegetc(); + +/* VS1053 */ +extern void clearXCS(); +extern void setXCS(); +extern int vs10XXDREQ(); + + +#endif + + + + + + + + + + diff --git a/bsp/src/LandTiger/Makefile b/bsp/src/LandTiger/Makefile --- a/bsp/src/LandTiger/Makefile +++ b/bsp/src/LandTiger/Makefile @@ -5,12 +5,15 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_BSP_INC_DIR)/LandTiger HEADERS += bsp.h LIBSOURCES += bsp.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc17XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc TARGET=libbsp -LIBUC_INCLUDES=$(LIBUC_INC_DIR_SDCARD_CMD) $(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UART_CMD) $(LIBUC_INC_DIR_SSP_CMD) $(LIBUC_INC_DIR_24LC0X_CMD) $(LIBUC_INC_DIR_IIC_CMD) $(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) -LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_SDCARD_CMD) $(LIBUC_LIBS_SDCARD) $(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UART_CMD) $(LIBUC_LIBS_UART) $(LIBUC_LIBS_DIR_SSP_CMD) $(LIBUC_LIBS_SSP) $(LIBUC_LIBS_DIR_24LC0X_CMD) $(LIBUC_LIBS_24LC0X) $(LIBUC_LIBS_DIR_IIC_CMD) $(LIBUC_LIBS_IIC) $(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) +LIBUC_INCLUDES=$(LIBUC_INC_DIR_ALLFS_CMD) $(LIBUC_INC_DIR_UART_CMD) $(LIBUC_INC_DIR_SSP_CMD) $(LIBUC_INC_DIR_24LC0X_CMD) $(LIBUC_INC_DIR_IIC_CMD) $(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_ALLFS_CMD) $(LIBUC_LIBS_ALLFS) $(LIBUC_LIBS_DIR_UART_CMD) $(LIBUC_LIBS_UART) $(LIBUC_LIBS_DIR_SSP_CMD) $(LIBUC_LIBS_SSP) $(LIBUC_LIBS_DIR_24LC0X_CMD) $(LIBUC_LIBS_24LC0X) $(LIBUC_LIBS_DIR_IIC_CMD) $(LIBUC_LIBS_IIC) $(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) TARGETINSTALLPATH=$(LIBUC_BSP_BIN_DIR)/LandTiger HEADERSINSTALLPATH=$(LIBUC_BSP_INC_DIR)/LandTiger BSP=generic @@ -18,3 +21,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/bsp/src/LandTiger/bsp.c b/bsp/src/LandTiger/bsp.c --- a/bsp/src/LandTiger/bsp.c +++ b/bsp/src/LandTiger/bsp.c @@ -28,20 +28,23 @@ unsigned int INTOSC =4000000; unsigned int RTCOSC =32768; unsigned int currentCpuFreq=0; float VREF0 =(float)3.3; -uartDev* UART0=(uartDev*)0; -uartDev* UART1=(uartDev*)0; -uartDev* UART2=(uartDev*)0; -uartDev* UART3=(uartDev*)0; +uartDev UART0=(uartDev)0; +uartDev UART1=(uartDev)0; +uartDev UART2=(uartDev)0; +uartDev UART3=(uartDev)0; -i2cDev* IIC0=(i2cDev*)0; -i2cDev* IIC1=(i2cDev*)0; -i2cDev* IIC2=(i2cDev*)0; +i2cDev IIC0=(i2cDev)0; +i2cDev IIC1=(i2cDev)0; +i2cDev IIC2=(i2cDev)0; -sspDev* SSP0=(sspDev*)0; -sspDev* SSP1=(sspDev*)0; +sspDev SSP0=(sspDev)0; +sspDev SSP1=(sspDev)0; sdcardDev SDCARD0; blkdevice BLKDEVSDCARD0; +dikpartition PART0; +FAT32fs fs0; +ucdirent root; eeprom24lc0xDev eeprom0; @@ -121,9 +124,12 @@ void bsp_SD_init() LPC_GPIO3->FIODIR |=1<<26; LPC_GPIO3->FIODIR &= ~(1<<25); LPC_GPIO3->FIOCLR |=1<<26; - sdcardmake(&SDCARD0,SSP0,&sspgetnc,&sspputnc,&sspsetdatarate); + sdcardmake(&SDCARD0,SSP0,&sspgetnc,&sspputnc,&sspsetdatarate,&sspgetdatarate); sdcardmakeblkdev(&BLKDEVSDCARD0,&SDCARD0,&bspsdcardselect,&bsppowersdcard,&bspsdcardpresent,&bspsdcardwriteprotected); - //BLKDEVSDCARD0.initialize(&BLKDEVSDCARD0,0); + BLKDEVSDCARD0.initialize(&BLKDEVSDCARD0); + mbropen(&BLKDEVSDCARD0,&PART0,1); + fat32open(&fs0,&PART0); + fat32mkdirent(&fs0,&root); } void consoleputc(char c) diff --git a/bsp/src/LandTiger/bsp.h b/bsp/src/LandTiger/bsp.h --- a/bsp/src/LandTiger/bsp.h +++ b/bsp/src/LandTiger/bsp.h @@ -28,22 +28,27 @@ #include <24LC0X.h> #include #include +#include +#include -extern uartDev* UART0; -extern uartDev* UART1; -extern uartDev* UART2; -extern uartDev* UART3; +extern uartDev UART0; +extern uartDev UART1; +extern uartDev UART2; +extern uartDev UART3; -extern i2cDev* IIC0; -extern i2cDev* IIC1; -extern i2cDev* IIC2; +extern i2cDev IIC0; +extern i2cDev IIC1; +extern i2cDev IIC2; -extern sspDev* SSP0; -extern sspDev* SSP1; +extern sspDev SSP0; +extern sspDev SSP1; extern sdcardDev SDCARD0; extern blkdevice BLKDEVSDCARD0; +extern dikpartition PART0; +extern FAT32fs fs0; +extern ucdirent root; extern eeprom24lc0xDev eeprom0; diff --git a/bsp/src/LandTiger/landtiger.pro b/bsp/src/LandTiger/landtiger.pro --- a/bsp/src/LandTiger/landtiger.pro +++ b/bsp/src/LandTiger/landtiger.pro @@ -4,7 +4,7 @@ TARGET = libbsp TARGETINSTALLPATH = $(LIBUC_BSP_BIN_DIR)/LandTiger HEADERSINSTALLPATH = $(LIBUC_BSP_INC_DIR)/LandTiger -LIBS += SDCARD BLKDEVICE UART SSP 24LC0X IIC CORE UCSTRINGS +LIBS += ALLFS UART SSP 24LC0X IIC CORE UCSTRINGS UHANDLE SOURCES += bsp.c diff --git a/bsp/src/LandTigerdualssp/Makefile b/bsp/src/LandTigerdualssp/Makefile new file mode 100644 --- /dev/null +++ b/bsp/src/LandTigerdualssp/Makefile @@ -0,0 +1,30 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_BSP_INC_DIR)/LandTigerdualssp +HEADERS += bsp.h +LIBSOURCES += bsp.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc17XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc +TARGET=libbsp +LIBUC_INCLUDES=$(LIBUC_INC_DIR_ALLFS_CMD) $(LIBUC_INC_DIR_UART_CMD) $(LIBUC_INC_DIR_SSP_CMD) $(LIBUC_INC_DIR_24LC0X_CMD) $(LIBUC_INC_DIR_IIC_CMD) $(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_ALLFS_CMD) $(LIBUC_LIBS_ALLFS) $(LIBUC_LIBS_DIR_UART_CMD) $(LIBUC_LIBS_UART) $(LIBUC_LIBS_DIR_SSP_CMD) $(LIBUC_LIBS_SSP) $(LIBUC_LIBS_DIR_24LC0X_CMD) $(LIBUC_LIBS_24LC0X) $(LIBUC_LIBS_DIR_IIC_CMD) $(LIBUC_LIBS_IIC) $(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_BSP_BIN_DIR)/LandTigerdualssp +HEADERSINSTALLPATH=$(LIBUC_BSP_INC_DIR)/LandTigerdualssp +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/bsp/src/LandTigerdualssp/bsp.c b/bsp/src/LandTigerdualssp/bsp.c new file mode 100644 --- /dev/null +++ b/bsp/src/LandTigerdualssp/bsp.c @@ -0,0 +1,191 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#include "bsp.h" +#include "core.h" + + +unsigned int OSC0 =12000000; +unsigned int INTOSC =4000000; +unsigned int RTCOSC =32768; +unsigned int currentCpuFreq=0; +float VREF0 =(float)3.3; +uartDev UART0=(uartDev)0; +uartDev UART1=(uartDev)0; +uartDev UART2=(uartDev)0; +uartDev UART3=(uartDev)0; + +i2cDev IIC0=(i2cDev)0; +i2cDev IIC1=(i2cDev)0; +i2cDev IIC2=(i2cDev)0; + +sspDev SSP0=(sspDev)0; +sspDev SSP1=(sspDev)0; + +sdcardDev SDCARD0; +blkdevice BLKDEVSDCARD0; +dikpartition PART0; +FAT32fs fs0; +ucdirent root; + +eeprom24lc0xDev eeprom0; + +int bsp_init() +{ + bsp_GPIO_init(); + coresetCpuFreq(20000000); + currentCpuFreq=coregetCpuFreq(); + coresetCpuFreq(60000000); + currentCpuFreq=coregetCpuFreq(); + bsp_uart_init(); + bsp_iic_init(); + bsp_ssp_init(); + bsp_SD_init(); + return 0; +} + +void bsp_GPIO_init() +{ + LPC_SC->PCONP |= ( 1 << 15 ); // power up GPIO + LPC_GPIO2->FIODIR |=255; + LEDS_OFF; +} + +void bsp_uart_init() +{ + LPC_SC->PCONP |= ( 1 << 24 ); // power up UART3 + LPC_SC->PCONP |= ( 1 << 4 ); // power up UART1 + LPC_PINCON->PINSEL0 |= (1<<4); + LPC_PINCON->PINSEL0 &= ~(1<<5); + LPC_PINCON->PINSEL0 |= (1<<6); + LPC_PINCON->PINSEL0 &= ~(1<<7); + LPC_PINCON->PINSEL0 |= (1<<20); + LPC_PINCON->PINSEL0 &= ~(1<<21); + LPC_PINCON->PINSEL0 |= (1<<22); + LPC_PINCON->PINSEL0 &= ~(1<<23); + UART0= uartopen(0); + uartsetup(UART0,38400,8,1,uartNoParity); + UART2= uartopen(2); + uartsetup(UART2,38400,8,1,uartNoParity); +} + +void bsp_ssp_init() +{ + SSP0 = sspopen(0); // power up SSP0 + SSP1 = sspopen(1); + ssppowerup(SSP0); + ssppowerup(SSP1); + sspsetpclkfactor(SSP0,1); + sspsetpclkfactor(SSP1,1); + sspsetup(SSP0,16,FFSPI|CLKINHLOW|CKfirstEdge,loopbackOFF|MASTERMODE, 350000); + sspsetup(SSP1,16,FFSPI|CLKINHLOW|CKfirstEdge,loopbackOFF|MASTERMODE, 350000); + enableSSP(SSP0); + enableSSP(SSP1); + LPC_PINCON->PINSEL3 |= (3<<14); //MISO0 on P1.23 + LPC_PINCON->PINSEL3 |= (3<<16); //MOSI0 on P1.24 + LPC_PINCON->PINSEL3 |= (3<<8); //SCK0 on P1.20 + LPC_PINCON->PINSEL0 |= (1<<17); //MISO0 on P1.23 + LPC_PINCON->PINSEL0 &= ~(1<<16); + LPC_PINCON->PINSEL0 |= (1<<19); //MOSI0 on P1.24 + LPC_PINCON->PINSEL0 &= ~(1<<18); //MOSI0 on P1.24 + LPC_PINCON->PINSEL0 |= (1<<15); //SCK0 on P1.20 + LPC_PINCON->PINSEL0 &= ~(1<<14); //SCK0 on P1.20 + LPC_GPIO1->FIODIR |= (1<<24) + (1<<20); + LPC_PINCON->PINMODE3 &= ~(1<<14); + LPC_PINCON->PINMODE3 &= ~(1<<15); + //LPC_PINCON->PINSEL3 |= (3<<10); //SSEL0 on P1.21 disable for SDCARD -> need to send dummy clock + +} + + +void bsp_iic_init() +{ + /*LPC_SC->PCONP |= ( 1 << 7 ); // power up IIC0 + LPC_PINCON->PINSEL1 |= (1<<22); + LPC_PINCON->PINSEL1 &= ~(1<<23); + LPC_PINCON->PINSEL1 |= (1<<24); + LPC_PINCON->PINSEL1 &= ~(1<<25); + IIC0 = i2copen(0); + i2csetdatarate(IIC0,100000); + eeprom24lc0xopen(&eeprom0,IIC0,0,2048);*/ +} + +void bsp_SD_init() +{ + /*LPC_GPIO1->FIODIR |=1<<21; //SD chip select on P1.21 + LPC_GPIO1->FIOSET = 1<<21; //unselect SD card + LPC_GPIO3->FIODIR |=1<<26; + LPC_GPIO3->FIODIR &= ~(1<<25); + LPC_GPIO3->FIOCLR |=1<<26; + sdcardmake(&SDCARD0,SSP0,&sspgetnc,&sspputnc,&sspsetdatarate,&sspgetdatarate); + sdcardmakeblkdev(&BLKDEVSDCARD0,&SDCARD0,&bspsdcardselect,&bsppowersdcard,&bspsdcardpresent,&bspsdcardwriteprotected); + BLKDEVSDCARD0.initialize(&BLKDEVSDCARD0); + mbropen(&BLKDEVSDCARD0,&PART0,1); + fat32open(&fs0,&PART0); + fat32mkdirent(&fs0,&root);*/ +} + +void consoleputc(char c) +{ + uartputc(UART0,c); +} + + +char consolegetc() +{ + return uartgetc(UART0); +} + + + +void vs10XXclearXCS(){} +void vs10XXsetXCS(){} +int vs10XXDREQ() +{ + return 1; +} + + +void bsppowersdcard(char onoff) //always ON +{ + +} + +char bspsdcardpresent() +{ + return (((LPC_GPIO3->FIOPIN >> 25) & 1) ^1); +} + +char bspsdcardwriteprotected() +{ + return 0; +} + +void bspsdcardselect(char YESNO) +{ + + LPC_GPIO1->FIOPIN = ((YESNO & 1)^1)<<21; +} + + + + + diff --git a/bsp/src/LandTigerdualssp/bsp.h b/bsp/src/LandTigerdualssp/bsp.h new file mode 100644 --- /dev/null +++ b/bsp/src/LandTigerdualssp/bsp.h @@ -0,0 +1,129 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef BSP_H +#define BSP_H +#include "LPC17xx.h" +#include +#include +#include +#include <24LC0X.h> +#include +#include +#include +#include + + +extern uartDev UART0; +extern uartDev UART1; +extern uartDev UART2; +extern uartDev UART3; + +extern i2cDev IIC0; +extern i2cDev IIC1; +extern i2cDev IIC2; + +extern sspDev SSP0; +extern sspDev SSP1; + +extern sdcardDev SDCARD0; +extern blkdevice BLKDEVSDCARD0; +extern dikpartition PART0; +extern FAT32fs fs0; +extern ucdirent root; + +extern eeprom24lc0xDev eeprom0; + +extern float VREF0; + +extern unsigned int currentCpuFreq; + +#define pll0useInternal 0 +#define pll0useMainOsc 1 +#define pll0useRTC 2 + + +#define pll0setClksrc(src) if((unsigned int)(src)<3) LPC_SC->CLKSRCSEL=(src) +#define pll0getClksrc (LPC_SC->CLKSRCSEL & 3) + +#define LEDS_ON LPC_GPIO2->FIOSET = 255 + +#define LED1_ON LPC_GPIO2->FIOSET = (1<<0) +#define LED2_ON LPC_GPIO2->FIOSET = (1<<1) +#define LED3_ON LPC_GPIO2->FIOSET = (1<<2) +#define LED4_ON LPC_GPIO2->FIOSET = (1<<3) +#define LED5_ON LPC_GPIO2->FIOSET = (1<<4) +#define LED6_ON LPC_GPIO2->FIOSET = (1<<5) +#define LED7_ON LPC_GPIO2->FIOSET = (1<<6) +#define LED8_ON LPC_GPIO2->FIOSET = (1<<7) + +#define LEDS_OFF LPC_GPIO2->FIOCLR = ~(255) + +#define LED1_OFF LPC_GPIO2->FIOCLR = (1<<0) +#define LED2_OFF LPC_GPIO2->FIOCLR = (1<<1) +#define LED3_OFF LPC_GPIO2->FIOCLR = (1<<2) +#define LED4_OFF LPC_GPIO2->FIOCLR = (1<<3) +#define LED5_OFF LPC_GPIO2->FIOCLR = (1<<4) +#define LED6_OFF LPC_GPIO2->FIOCLR = (1<<5) +#define LED7_OFF LPC_GPIO2->FIOCLR = (1<<6) +#define LED8_OFF LPC_GPIO2->FIOCLR = (1<<7) + +extern int bsp_init(); + +extern void bsp_GPIO_init(); +extern void bsp_uart_init(); +extern void bsp_iic_init(); +extern void bsp_ssp_init(); +extern void bsp_SD_init(); +extern void consoleputc(char); +extern char consolegetc(); + +/* VS1053 */ +extern void clearXCS(); +extern void setXCS(); +extern int vs10XXDREQ(); + +/* SD CARD */ +void bsppowersdcard(char onoff); +char bspsdcardpresent(); +void bspsdcardselect(char YESNO); +char bspsdcardwriteprotected(); + +#endif + + + + + + + + + + + + + + + + + + + diff --git a/bsp/src/LandTigerdualssp/landtiger.pro b/bsp/src/LandTigerdualssp/landtiger.pro new file mode 100644 --- /dev/null +++ b/bsp/src/LandTigerdualssp/landtiger.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +ARCH = lpc17XX-arm-noabi-gcc +TARGET = libbsp +TARGETINSTALLPATH = $(LIBUC_BSP_BIN_DIR)/LandTigerdualssp +HEADERSINSTALLPATH = $(LIBUC_BSP_INC_DIR)/LandTigerdualssp + +LIBS += ALLFS UART SSP 24LC0X IIC CORE UCSTRINGS UHANDLE + +SOURCES += bsp.c + + +HEADERS += bsp.h diff --git a/bsp/src/MP3PlayerV1/MP3PlayerV1.pro b/bsp/src/MP3PlayerV1/MP3PlayerV1.pro new file mode 100644 --- /dev/null +++ b/bsp/src/MP3PlayerV1/MP3PlayerV1.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +ARCH = lpc21XX-arm-noabi-gcc +TARGET = libbsp +TARGETINSTALLPATH = $(LIBUC_BSP_BIN_DIR)/MP3PlayerV1 +HEADERSINSTALLPATH = $(LIBUC_BSP_INC_DIR)/MP3PlayerV1 + +LIBS += UART CORE UHANDLE + +SOURCES += bsp.c + + +HEADERS += bsp.h diff --git a/bsp/src/MP3PlayerV1/Makefile b/bsp/src/MP3PlayerV1/Makefile new file mode 100644 --- /dev/null +++ b/bsp/src/MP3PlayerV1/Makefile @@ -0,0 +1,30 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_BSP_INC_DIR)/MP3PlayerV1 +HEADERS += bsp.h +LIBSOURCES += bsp.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libbsp +LIBUC_INCLUDES=$(LIBUC_INC_DIR_UART_CMD) $(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_UART_CMD) $(LIBUC_LIBS_UART) $(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_BSP_BIN_DIR)/MP3PlayerV1 +HEADERSINSTALLPATH=$(LIBUC_BSP_INC_DIR)/MP3PlayerV1 +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/bsp/src/MP3PlayerV1/bsp.c b/bsp/src/MP3PlayerV1/bsp.c new file mode 100644 --- /dev/null +++ b/bsp/src/MP3PlayerV1/bsp.c @@ -0,0 +1,136 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#include "bsp.h" +#include "core.h" + + +unsigned int OSC0 =12000000; +unsigned int INTOSC =4000000; +unsigned int RTCOSC =32768; +unsigned int currentCpuFreq=0; +float VREF0 =(float)3.3; +uartDev* UART0=(uartDev*)0; +uartDev* UART1=(uartDev*)0; +uartDev* UART2=(uartDev*)0; +uartDev* UART3=(uartDev*)0; +/* +i2cDev* IIC0=(i2cDev*)0; +i2cDev* IIC1=(i2cDev*)0; +i2cDev* IIC2=(i2cDev*)0; + +sspDev* SSP0=(sspDev*)0; +sspDev* SSP1=(sspDev*)0; + +eeprom24lc0xDev eeprom0;*/ + +int bsp_init() +{ + bsp_GPIO_init(); + //coresetCpuFreq(20000000); + //currentCpuFreq=coregetCpuFreq(); + //coresetCpuFreq(60000000); + //currentCpuFreq=coregetCpuFreq(); + bsp_uart_init(); + bsp_iic_init(); + bsp_ssp_init(); + return 0; +} + +void bsp_GPIO_init() +{ + /*PCONP |= ( 1 << 15 ); // power up GPIO + FIO2DIR |=255; + LEDS_OFF;*/ +} + +void bsp_uart_init() +{ + /*PCONP |= ( 1 << 24 ); // power up UART3 + PCONP |= ( 1 << 4 ); // power up UART1 + PINSEL0 |= (1<<4); + PINSEL0 &= ~(1<<5); + PINSEL0 |= (1<<6); + PINSEL0 &= ~(1<<7); + PINSEL0 |= (1<<20); + PINSEL0 &= ~(1<<21); + PINSEL0 |= (1<<22); + PINSEL0 &= ~(1<<23);*/ + UART0= uartopen(0); + //uartsetup(UART0,38400,8,1,uartNoParity); + /*UART2= uartopen(2); + uartsetup(UART2,38400,8,1,uartNoParity);*/ +} + +void bsp_ssp_init() +{ + /*SSP0 = sspopen(0); // power up SSP0 + ssppowerup(SSP0); + sspsetpclkfactor(SSP0,1); + PINSEL3 |= (3<<14); //MISO0 on P1.23 + PINSEL3 |= (3<<16); //MOSI0 on P1.24 + PINSEL3 |= (3<<8); //SCK0 on P1.24 + PINSEL3 |= (3<<10); //SSEL0 on P1.21 + sspsetup(SSP0,8,FFSPI|CLKINHLOW|CKfirstEdge,loopbackOFF|MASTERMODE, 250000); + enableSSP(SSP0);*/ +} + + +void bsp_iic_init() +{ + /*LPC_SC->PCONP |= ( 1 << 7 ); // power up IIC0 + PINSEL1 |= (1<<22); + PINSEL1 &= ~(1<<23); + PINSEL1 |= (1<<24); + PINSEL1 &= ~(1<<25); + IIC0 = i2copen(0); + i2csetdatarate(IIC0,100000); + eeprom24lc0xopen(&eeprom0,IIC0,0,2048);*/ +} + +void consoleputc(char c) +{ + uartputc(UART0,c); +} + + +char consolegetc() +{ + return uartgetc(UART0); +} + + + +void vs10XXclearXCS(){} +void vs10XXsetXCS(){} +int vs10XXDREQ() +{ + return 1; +} + + + + + + + + + diff --git a/bsp/src/MP3PlayerV1/bsp.h b/bsp/src/MP3PlayerV1/bsp.h new file mode 100644 --- /dev/null +++ b/bsp/src/MP3PlayerV1/bsp.h @@ -0,0 +1,101 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef BSP_H +#define BSP_H +#include "LPC23xx.h" +#include + + +extern uartDev* UART0; +extern uartDev* UART1; +extern uartDev* UART2; +extern uartDev* UART3; + +/*extern i2cDev* IIC0; +extern i2cDev* IIC1; +extern i2cDev* IIC2; + +extern sspDev* SSP0; +extern sspDev* SSP1; + +extern eeprom24lc0xDev eeprom0;*/ + +extern float VREF0; + +extern unsigned int currentCpuFreq; + +#define pll0useInternal 0 +#define pll0useMainOsc 1 +#define pll0useRTC 2 + + +#define pll0setClksrc(src) if((unsigned int)(src)<3) CLKSRCSEL=(src) +#define pll0getClksrc (CLKSRCSEL & 3) + +#define LEDS_ON + +#define LED1_ON +#define LED2_ON +#define LED3_ON +#define LED4_ON +#define LED5_ON +#define LED6_ON +#define LED7_ON +#define LED8_ON + +#define LEDS_OFF + +#define LED1_OFF +#define LED2_OFF +#define LED3_OFF +#define LED4_OFF +#define LED5_OFF +#define LED6_OFF +#define LED7_OFF +#define LED8_OFF + +extern int bsp_init(); + +extern void bsp_GPIO_init(); +extern void bsp_uart_init(); +extern void bsp_iic_init(); +extern void bsp_ssp_init(); +extern void consoleputc(char); +extern char consolegetc(); + +/* VS1053 */ +extern void clearXCS(); +extern void setXCS(); +extern int vs10XXDREQ(); + + +#endif + + + + + + + + + + diff --git a/bsp/src/MP3PlayerV1/crt0.c b/bsp/src/MP3PlayerV1/crt0.c new file mode 100644 --- /dev/null +++ b/bsp/src/MP3PlayerV1/crt0.c @@ -0,0 +1,195 @@ +asm{ + .global main // int main(void) + + .global _etext // -> .data initial values in ROM + .global _data // -> .data area in RAM + .global _edata // end of .data area + .global __bss_start // -> .bss area in RAM + .global __bss_end__ // end of .bss area + .global _stack // top of stack + +// Stack Sizes + .set UND_STACK_SIZE, 0x00000004 + .set ABT_STACK_SIZE, 0x00000004 + .set FIQ_STACK_SIZE, 0x00000004 + .set IRQ_STACK_SIZE, 0X00000080 + .set SVC_STACK_SIZE, 0x00000004 + +// Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs + .set MODE_USR, 0x10 // User Mode + .set MODE_FIQ, 0x11 // FIQ Mode + .set MODE_IRQ, 0x12 // IRQ Mode + .set MODE_SVC, 0x13 // Supervisor Mode + .set MODE_ABT, 0x17 // Abort Mode + .set MODE_UND, 0x1B // Undefined Mode + .set MODE_SYS, 0x1F // System Mode + + .equ I_BIT, 0x80 // when I bit is set, IRQ is disabled + .equ F_BIT, 0x40 // when F bit is set, FIQ is disabled + + .text + .code 32 + .align 2 + + .global _boot + .func _boot +_boot: + +// Runtime Interrupt Vectors +// ------------------------- +Vectors: + b _start // reset - _start + ldr pc,_undf // undefined - _undf + ldr pc,_swi // SWI - _swi + ldr pc,_pabt // program abort - _pabt + ldr pc,_dabt // data abort - _dabt + nop // reserved + ldr pc,[pc,#-0xFF0] // IRQ - read the VIC + ldr pc,_fiq // FIQ - _fiq + +#if 0 +// Use this group for production +_undf: .word _reset // undefined - _reset +_swi: .word _reset // SWI - _reset +_pabt: .word _reset // program abort - _reset +_dabt: .word _reset // data abort - _reset +_irq: .word _reset // IRQ - _reset +_fiq: .word _reset // FIQ - _reset + +#else +// Use this group for development +_undf: .word __undf // undefined +_swi: .word __swi // SWI +_pabt: .word __pabt // program abort +_dabt: .word __dabt // data abort +_irq: .word __irq // IRQ +_fiq: .word __fiq // FIQ + +__undf: b . // undefined +__swi: b . // SWI +__pabt: b . // program abort +__dabt: b . // data abort +__irq: b . // IRQ +__fiq: b . // FIQ +#endif + .size _boot, . - _boot + .endfunc + + +// Setup the operating mode & stack. +// --------------------------------- + .global _start, start, _mainCRTStartup + .func _start + +_start: +start: +_mainCRTStartup: + +// Initialize Interrupt System +// - Set stack location for each mode +// - Leave in System Mode with Interrupts Disabled +// ----------------------------------------------- + ldr r0,=_stack + msr CPSR_c,#MODE_UND|I_BIT|F_BIT // Undefined Instruction Mode + mov sp,r0 + sub r0,r0,#UND_STACK_SIZE + msr CPSR_c,#MODE_ABT|I_BIT|F_BIT // Abort Mode + mov sp,r0 + sub r0,r0,#ABT_STACK_SIZE + msr CPSR_c,#MODE_FIQ|I_BIT|F_BIT // FIQ Mode + mov sp,r0 + sub r0,r0,#FIQ_STACK_SIZE + msr CPSR_c,#MODE_IRQ|I_BIT|F_BIT // IRQ Mode + mov sp,r0 + sub r0,r0,#IRQ_STACK_SIZE + msr CPSR_c,#MODE_SVC|I_BIT|F_BIT // Supervisor Mode + mov sp,r0 + sub r0,r0,#SVC_STACK_SIZE + msr CPSR_c,#MODE_SYS|I_BIT|F_BIT // System Mode + mov sp,r0 + +// Copy initialized data to its execution address in RAM +// ----------------------------------------------------- +#ifdef ROM_RUN + ldr r1,=_etext // -> ROM data start + ldr r2,=_data // -> data start + ldr r3,=_edata // -> end of data +1: cmp r2,r3 // check if data to move + ldrlo r0,[r1],#4 // copy it + strlo r0,[r2],#4 + blo 1b // loop until done +#endif +// Clear .bss +// ---------- + mov r0,#0 // get a zero + ldr r1,=__bss_start // -> bss start + ldr r2,=__bss_end__ // -> bss end +2: cmp r1,r2 // check if data to clear + strlo r0,[r1],#4 // clear 4 bytes + blo 2b // loop until done + +/* + Call C++ constructors (for objects in "global scope") + ctor loop added by Martin Thomas 4/2005 + based on a Anglia Design example-application for ST ARM +*/ + + LDR r0, =__ctors_start__ + LDR r1, =__ctors_end__ +ctor_loop: + CMP r0, r1 + BEQ ctor_end + LDR r2, [r0], #4 + STMFD sp!, {r0-r1} + MOV lr, pc + MOV pc, r2 + LDMFD sp!, {r0-r1} + B ctor_loop +ctor_end: + +// Call main program: main(0) +// -------------------------- + mov r0,#0 // no arguments (argc = 0) + mov r1,r0 + mov r2,r0 + mov fp,r0 // null frame pointer + mov r7,r0 // null frame pointer for thumb + ldr r10,=main + mov lr,pc + bx r10 // enter main() + +/* "global object"-dtors are never called and it should not be + needed since there is no OS to exit to. */ + + .size _start, . - _start + .endfunc + + .global _reset, reset, exit, abort + .func _reset +_reset: +reset: +exit: +abort: +#if 0 +// Disable interrupts, then force a hardware reset by driving P23 low +// ------------------------------------------------------------------- + mrs r0,cpsr // get PSR + orr r0,r0,#I_BIT|F_BIT // disable IRQ and FIQ + msr cpsr,r0 // set up status register + + ldr r1,=(PS_BASE) // PS Base Address + ldr r0,=(PS_PIO) // PIO Module + str r0,[r1,#PS_PCER_OFF] // enable its clock + ldr r1,=(PIO_BASE) // PIO Base Address + ldr r0,=(1<<23) // P23 + str r0,[r1,#PIO_PER_OFF] // make sure pin is contolled by PIO + str r0,[r1,#PIO_CODR_OFF] // set the pin low + str r0,[r1,#PIO_OER_OFF] // make it an output +#endif + b . // loop until reset + + .size _reset, . - _reset + .endfunc + + .end +} diff --git a/bsp/src/Makefile b/bsp/src/Makefile --- a/bsp/src/Makefile +++ b/bsp/src/Makefile @@ -6,12 +6,14 @@ include $(LIBUC)/rules/common/rules.mk all:subdir make -C generic make -C LandTiger + make -C LandTigerdualssp make -C mbed @echo Code compiled clean: make clean -C generic make clean -C LandTiger + make clean -C LandTigerdualssp make clean -C mbed @echo Code compiled diff --git a/bsp/src/bsp.pro b/bsp/src/bsp.pro --- a/bsp/src/bsp.pro +++ b/bsp/src/bsp.pro @@ -1,4 +1,5 @@ TEMPLATE = dir SUBDIRS += generic \ LandTiger \ + LandTigerdualssp \ mbed diff --git a/bsp/src/generic/Makefile b/bsp/src/generic/Makefile --- a/bsp/src/generic/Makefile +++ b/bsp/src/generic/Makefile @@ -5,7 +5,10 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_BSP_INC_DIR)/generic HEADERS += bsp.h LIBSOURCES += bsp.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc17XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc TARGET=libbsp @@ -18,3 +21,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/bsp/src/mbed/Makefile b/bsp/src/mbed/Makefile --- a/bsp/src/mbed/Makefile +++ b/bsp/src/mbed/Makefile @@ -5,12 +5,15 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_BSP_INC_DIR)/mbed HEADERS += bsp.h LIBSOURCES += bsp.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc17XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc TARGET=libbsp -LIBUC_INCLUDES=$(LIBUC_INC_DIR_UART_CMD) $(LIBUC_INC_DIR_CORE_CMD) -LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_UART_CMD) $(LIBUC_LIBS_UART) $(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) +LIBUC_INCLUDES=$(LIBUC_INC_DIR_UART_CMD) $(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_UART_CMD) $(LIBUC_LIBS_UART) $(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) TARGETINSTALLPATH=$(LIBUC_BSP_BIN_DIR)/mbed HEADERSINSTALLPATH=$(LIBUC_BSP_INC_DIR)/mbed BSP=generic @@ -18,3 +21,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/bsp/src/mbed/bsp.c b/bsp/src/mbed/bsp.c --- a/bsp/src/mbed/bsp.c +++ b/bsp/src/mbed/bsp.c @@ -27,10 +27,10 @@ unsigned int OSC0 =12000000; unsigned int INTOSC =4000000; unsigned int RTCOSC =32768; unsigned int currentCpuFreq=0; -uartDev* UART0=(uartDev*)0; -uartDev* UART1=(uartDev*)0; -uartDev* UART2=(uartDev*)0; -uartDev* UART3=(uartDev*)0; +uartDev UART0=(uartDev)0; +uartDev UART1=(uartDev)0; +uartDev UART2=(uartDev)0; +uartDev UART3=(uartDev)0; int bsp_init() diff --git a/bsp/src/mbed/bsp.h b/bsp/src/mbed/bsp.h --- a/bsp/src/mbed/bsp.h +++ b/bsp/src/mbed/bsp.h @@ -24,10 +24,10 @@ #include "LPC17xx.h" #include -extern uartDev* UART0; -extern uartDev* UART1; -extern uartDev* UART2; -extern uartDev* UART3; +extern uartDev UART0; +extern uartDev UART1; +extern uartDev UART2; +extern uartDev UART3; #define VREF0 (float)3.3 diff --git a/bsp/src/mbed/mbed.pro b/bsp/src/mbed/mbed.pro --- a/bsp/src/mbed/mbed.pro +++ b/bsp/src/mbed/mbed.pro @@ -4,7 +4,7 @@ TARGET = libbsp TARGETINSTALLPATH = $(LIBUC_BSP_BIN_DIR)/mbed HEADERSINSTALLPATH = $(LIBUC_BSP_INC_DIR)/mbed -LIBS += UART CORE +LIBS += UART CORE UHANDLE SOURCES += bsp.c diff --git a/examples/MP3Player/MP3Player.pro b/examples/MP3Player/MP3Player.pro new file mode 100644 --- /dev/null +++ b/examples/MP3Player/MP3Player.pro @@ -0,0 +1,3 @@ +TEMPLATE = dir +SUBDIRS += helloworld + diff --git a/examples/MP3Player/Makefile b/examples/MP3Player/Makefile new file mode 100644 --- /dev/null +++ b/examples/MP3Player/Makefile @@ -0,0 +1,13 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 +include $(LIBUC)/rules/common/rules.mk + +all:subdir + make -C helloworld + @echo Code compiled + +clean: + make clean -C helloworld + @echo Code compiled + diff --git a/examples/MP3Player/helloworld/Makefile b/examples/MP3Player/helloworld/Makefile new file mode 100644 --- /dev/null +++ b/examples/MP3Player/helloworld/Makefile @@ -0,0 +1,23 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERS += +APPSOURCES += main.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(APPSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=helloworld +LIBUC_INCLUDES=$(LIBUC_INC_DIR_UART_CMD) $(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_UART_CMD) $(LIBUC_LIBS_UART) $(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH= +HEADERSINSTALLPATH= +BSP=MP3PlayerV1 +include $(ARCHFOLDER)/rules.mk + +all:bin + @echo Code compiled + diff --git a/examples/MP3Player/helloworld/crt0.S b/examples/MP3Player/helloworld/crt0.S new file mode 100644 --- /dev/null +++ b/examples/MP3Player/helloworld/crt0.S @@ -0,0 +1,193 @@ + .global main // int main(void) + + .global _etext // -> .data initial values in ROM + .global _data // -> .data area in RAM + .global _edata // end of .data area + .global __bss_start // -> .bss area in RAM + .global __bss_end__ // end of .bss area + .global _stack // top of stack + +// Stack Sizes + .set UND_STACK_SIZE, 0x00000004 + .set ABT_STACK_SIZE, 0x00000004 + .set FIQ_STACK_SIZE, 0x00000004 + .set IRQ_STACK_SIZE, 0X00000080 + .set SVC_STACK_SIZE, 0x00000004 + +// Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs + .set MODE_USR, 0x10 // User Mode + .set MODE_FIQ, 0x11 // FIQ Mode + .set MODE_IRQ, 0x12 // IRQ Mode + .set MODE_SVC, 0x13 // Supervisor Mode + .set MODE_ABT, 0x17 // Abort Mode + .set MODE_UND, 0x1B // Undefined Mode + .set MODE_SYS, 0x1F // System Mode + + .equ I_BIT, 0x80 // when I bit is set, IRQ is disabled + .equ F_BIT, 0x40 // when F bit is set, FIQ is disabled + + .text + .code 32 + .align 2 + + .global _boot + .func _boot +_boot: + +// Runtime Interrupt Vectors +// ------------------------- +Vectors: + b _start // reset - _start + ldr pc,_undf // undefined - _undf + ldr pc,_swi // SWI - _swi + ldr pc,_pabt // program abort - _pabt + ldr pc,_dabt // data abort - _dabt + nop // reserved + ldr pc,[pc,#-0xFF0] // IRQ - read the VIC + ldr pc,_fiq // FIQ - _fiq + +#if 0 +// Use this group for production +_undf: .word _reset // undefined - _reset +_swi: .word _reset // SWI - _reset +_pabt: .word _reset // program abort - _reset +_dabt: .word _reset // data abort - _reset +_irq: .word _reset // IRQ - _reset +_fiq: .word _reset // FIQ - _reset + +#else +// Use this group for development +_undf: .word __undf // undefined +_swi: .word __swi // SWI +_pabt: .word __pabt // program abort +_dabt: .word __dabt // data abort +_irq: .word __irq // IRQ +_fiq: .word __fiq // FIQ + +__undf: b . // undefined +__swi: b . // SWI +__pabt: b . // program abort +__dabt: b . // data abort +__irq: b . // IRQ +__fiq: b . // FIQ +#endif + .size _boot, . - _boot + .endfunc + + +// Setup the operating mode & stack. +// --------------------------------- + .global _start, start, _mainCRTStartup + .func _start + +_start: +start: +_mainCRTStartup: + +// Initialize Interrupt System +// - Set stack location for each mode +// - Leave in System Mode with Interrupts Disabled +// ----------------------------------------------- + ldr r0,=_stack + msr CPSR_c,#MODE_UND|I_BIT|F_BIT // Undefined Instruction Mode + mov sp,r0 + sub r0,r0,#UND_STACK_SIZE + msr CPSR_c,#MODE_ABT|I_BIT|F_BIT // Abort Mode + mov sp,r0 + sub r0,r0,#ABT_STACK_SIZE + msr CPSR_c,#MODE_FIQ|I_BIT|F_BIT // FIQ Mode + mov sp,r0 + sub r0,r0,#FIQ_STACK_SIZE + msr CPSR_c,#MODE_IRQ|I_BIT|F_BIT // IRQ Mode + mov sp,r0 + sub r0,r0,#IRQ_STACK_SIZE + msr CPSR_c,#MODE_SVC|I_BIT|F_BIT // Supervisor Mode + mov sp,r0 + sub r0,r0,#SVC_STACK_SIZE + msr CPSR_c,#MODE_SYS|I_BIT|F_BIT // System Mode + mov sp,r0 + +// Copy initialized data to its execution address in RAM +// ----------------------------------------------------- +#ifdef ROM_RUN + ldr r1,=_etext // -> ROM data start + ldr r2,=_data // -> data start + ldr r3,=_edata // -> end of data +1: cmp r2,r3 // check if data to move + ldrlo r0,[r1],#4 // copy it + strlo r0,[r2],#4 + blo 1b // loop until done +#endif +// Clear .bss +// ---------- + mov r0,#0 // get a zero + ldr r1,=__bss_start // -> bss start + ldr r2,=__bss_end__ // -> bss end +2: cmp r1,r2 // check if data to clear + strlo r0,[r1],#4 // clear 4 bytes + blo 2b // loop until done + +/* + Call C++ constructors (for objects in "global scope") + ctor loop added by Martin Thomas 4/2005 + based on a Anglia Design example-application for ST ARM +*/ + + LDR r0, =__ctors_start__ + LDR r1, =__ctors_end__ +ctor_loop: + CMP r0, r1 + BEQ ctor_end + LDR r2, [r0], #4 + STMFD sp!, {r0-r1} + MOV lr, pc + MOV pc, r2 + LDMFD sp!, {r0-r1} + B ctor_loop +ctor_end: + +// Call main program: main(0) +// -------------------------- + mov r0,#0 // no arguments (argc = 0) + mov r1,r0 + mov r2,r0 + mov fp,r0 // null frame pointer + mov r7,r0 // null frame pointer for thumb + ldr r10,=main + mov lr,pc + bx r10 // enter main() + +/* "global object"-dtors are never called and it should not be + needed since there is no OS to exit to. */ + + .size _start, . - _start + .endfunc + + .global _reset, reset, exit, abort + .func _reset +_reset: +reset: +exit: +abort: +#if 0 +// Disable interrupts, then force a hardware reset by driving P23 low +// ------------------------------------------------------------------- + mrs r0,cpsr // get PSR + orr r0,r0,#I_BIT|F_BIT // disable IRQ and FIQ + msr cpsr,r0 // set up status register + + ldr r1,=(PS_BASE) // PS Base Address + ldr r0,=(PS_PIO) // PIO Module + str r0,[r1,#PS_PCER_OFF] // enable its clock + ldr r1,=(PIO_BASE) // PIO Base Address + ldr r0,=(1<<23) // P23 + str r0,[r1,#PIO_PER_OFF] // make sure pin is contolled by PIO + str r0,[r1,#PIO_CODR_OFF] // set the pin low + str r0,[r1,#PIO_OER_OFF] // make it an output +#endif + b . // loop until reset + + .size _reset, . - _reset + .endfunc + + .end diff --git a/examples/MP3Player/helloworld/crt0.c b/examples/MP3Player/helloworld/crt0.c new file mode 100644 --- /dev/null +++ b/examples/MP3Player/helloworld/crt0.c @@ -0,0 +1,193 @@ + .global main // int main(void) + + .global _etext // -> .data initial values in ROM + .global _data // -> .data area in RAM + .global _edata // end of .data area + .global __bss_start // -> .bss area in RAM + .global __bss_end__ // end of .bss area + .global _stack // top of stack + +// Stack Sizes + .set UND_STACK_SIZE, 0x00000004 + .set ABT_STACK_SIZE, 0x00000004 + .set FIQ_STACK_SIZE, 0x00000004 + .set IRQ_STACK_SIZE, 0X00000080 + .set SVC_STACK_SIZE, 0x00000004 + +// Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs + .set MODE_USR, 0x10 // User Mode + .set MODE_FIQ, 0x11 // FIQ Mode + .set MODE_IRQ, 0x12 // IRQ Mode + .set MODE_SVC, 0x13 // Supervisor Mode + .set MODE_ABT, 0x17 // Abort Mode + .set MODE_UND, 0x1B // Undefined Mode + .set MODE_SYS, 0x1F // System Mode + + .equ I_BIT, 0x80 // when I bit is set, IRQ is disabled + .equ F_BIT, 0x40 // when F bit is set, FIQ is disabled + + .text + .code 32 + .align 2 + + .global _boot + .func _boot +_boot: + +// Runtime Interrupt Vectors +// ------------------------- +Vectors: + b _start // reset - _start + ldr pc,_undf // undefined - _undf + ldr pc,_swi // SWI - _swi + ldr pc,_pabt // program abort - _pabt + ldr pc,_dabt // data abort - _dabt + nop // reserved + ldr pc,[pc,#-0xFF0] // IRQ - read the VIC + ldr pc,_fiq // FIQ - _fiq + +#if 0 +// Use this group for production +_undf: .word _reset // undefined - _reset +_swi: .word _reset // SWI - _reset +_pabt: .word _reset // program abort - _reset +_dabt: .word _reset // data abort - _reset +_irq: .word _reset // IRQ - _reset +_fiq: .word _reset // FIQ - _reset + +#else +// Use this group for development +_undf: .word __undf // undefined +_swi: .word __swi // SWI +_pabt: .word __pabt // program abort +_dabt: .word __dabt // data abort +_irq: .word __irq // IRQ +_fiq: .word __fiq // FIQ + +__undf: b . // undefined +__swi: b . // SWI +__pabt: b . // program abort +__dabt: b . // data abort +__irq: b . // IRQ +__fiq: b . // FIQ +#endif + .size _boot, . - _boot + .endfunc + + +// Setup the operating mode & stack. +// --------------------------------- + .global _start, start, _mainCRTStartup + .func _start + +_start: +start: +_mainCRTStartup: + +// Initialize Interrupt System +// - Set stack location for each mode +// - Leave in System Mode with Interrupts Disabled +// ----------------------------------------------- + ldr r0,=_stack + msr CPSR_c,#MODE_UND|I_BIT|F_BIT // Undefined Instruction Mode + mov sp,r0 + sub r0,r0,#UND_STACK_SIZE + msr CPSR_c,#MODE_ABT|I_BIT|F_BIT // Abort Mode + mov sp,r0 + sub r0,r0,#ABT_STACK_SIZE + msr CPSR_c,#MODE_FIQ|I_BIT|F_BIT // FIQ Mode + mov sp,r0 + sub r0,r0,#FIQ_STACK_SIZE + msr CPSR_c,#MODE_IRQ|I_BIT|F_BIT // IRQ Mode + mov sp,r0 + sub r0,r0,#IRQ_STACK_SIZE + msr CPSR_c,#MODE_SVC|I_BIT|F_BIT // Supervisor Mode + mov sp,r0 + sub r0,r0,#SVC_STACK_SIZE + msr CPSR_c,#MODE_SYS|I_BIT|F_BIT // System Mode + mov sp,r0 + +// Copy initialized data to its execution address in RAM +// ----------------------------------------------------- +#ifdef ROM_RUN + ldr r1,=_etext // -> ROM data start + ldr r2,=_data // -> data start + ldr r3,=_edata // -> end of data +1: cmp r2,r3 // check if data to move + ldrlo r0,[r1],#4 // copy it + strlo r0,[r2],#4 + blo 1b // loop until done +#endif +// Clear .bss +// ---------- + mov r0,#0 // get a zero + ldr r1,=__bss_start // -> bss start + ldr r2,=__bss_end__ // -> bss end +2: cmp r1,r2 // check if data to clear + strlo r0,[r1],#4 // clear 4 bytes + blo 2b // loop until done + +/* + Call C++ constructors (for objects in "global scope") + ctor loop added by Martin Thomas 4/2005 + based on a Anglia Design example-application for ST ARM +*/ + + LDR r0, =__ctors_start__ + LDR r1, =__ctors_end__ +ctor_loop: + CMP r0, r1 + BEQ ctor_end + LDR r2, [r0], #4 + STMFD sp!, {r0-r1} + MOV lr, pc + MOV pc, r2 + LDMFD sp!, {r0-r1} + B ctor_loop +ctor_end: + +// Call main program: main(0) +// -------------------------- + mov r0,#0 // no arguments (argc = 0) + mov r1,r0 + mov r2,r0 + mov fp,r0 // null frame pointer + mov r7,r0 // null frame pointer for thumb + ldr r10,=main + mov lr,pc + bx r10 // enter main() + +/* "global object"-dtors are never called and it should not be + needed since there is no OS to exit to. */ + + .size _start, . - _start + .endfunc + + .global _reset, reset, exit, abort + .func _reset +_reset: +reset: +exit: +abort: +#if 0 +// Disable interrupts, then force a hardware reset by driving P23 low +// ------------------------------------------------------------------- + mrs r0,cpsr // get PSR + orr r0,r0,#I_BIT|F_BIT // disable IRQ and FIQ + msr cpsr,r0 // set up status register + + ldr r1,=(PS_BASE) // PS Base Address + ldr r0,=(PS_PIO) // PIO Module + str r0,[r1,#PS_PCER_OFF] // enable its clock + ldr r1,=(PIO_BASE) // PIO Base Address + ldr r0,=(1<<23) // P23 + str r0,[r1,#PIO_PER_OFF] // make sure pin is contolled by PIO + str r0,[r1,#PIO_CODR_OFF] // set the pin low + str r0,[r1,#PIO_OER_OFF] // make it an output +#endif + b . // loop until reset + + .size _reset, . - _reset + .endfunc + + .end diff --git a/examples/MP3Player/helloworld/helloworld.pro b/examples/MP3Player/helloworld/helloworld.pro new file mode 100644 --- /dev/null +++ b/examples/MP3Player/helloworld/helloworld.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +ARCH = lpc21XX-arm-noabi-gcc +TARGET = helloworld +BSP = MP3PlayerV1 + +LIBS += UART CORE UCSTRINGS UHANDLE + +SOURCES += main.c + + +HEADERS += + diff --git a/examples/MP3Player/helloworld/main.c b/examples/MP3Player/helloworld/main.c new file mode 100644 --- /dev/null +++ b/examples/MP3Player/helloworld/main.c @@ -0,0 +1,88 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ + +#include "LPC23xx.h" +#include "bsp.h" +#include "core.h" +#include "uart.h" +#include "libucstrings.h" + +#define __delay(t) for(volatile int i=0;i +#include +#include + #define __delay(t) for(volatile int i=0;iread(dev,sector,sectorIndex,1); + hexviewershow(sector,512,sectorIndex*512); + libucprintf("\n\r"); + libucprintf("________________________________________________________\n\r"); + } + +} + +int fsexplprintPartInfos(dikpartition* part) +{ + char sector[512]; + if(part) + { + libucprintf("\n\r"); + libucprintf("========================================================\n\r"); + libucprintf("=== P A R T I T I O N I N F O s P R I N T E R ====\n\r"); + libucprintf("========================================================\n\r"); + part->phy->read(part->phy,sector,part->LBABegin,1); + hexviewershow(sector,512,0); + libucprintf("\n\r"); + libucprintf("FAT32 PART lba begin = %d\n\r",0xFFFF & part->LBABegin); + libucprintf("________________________________________________________\n\r"); + } +} + + +int fsexplprintBootSector(blkdevice* dev) +{ + char sector[512]; + if(dev) + { + libucprintf("\n\r"); + libucprintf("========================================================\n\r"); + libucprintf("======== B O O T S E C T O R P R I N T E R =======\n\r"); + libucprintf("========================================================\n\r"); + dev->read(dev,sector,0,1); + hexviewershow(sector,512,0); + libucprintf("\n\r"); + libucprintf("________________________________________________________\n\r"); + } + +} + +int fsexplprintDirentInfos(ucdirent* dirent) +{ + if(dirent) + { + libucprintf("\n\r"); + libucprintf("========================================================\n\r"); + libucprintf("======== E N T R Y I N F O P R I N T E R =======\n\r"); + libucprintf("========================================================\n\r"); + libucprintf("Entry Name:\t"); + libucprintf(dirent->DIR_Name); + libucprintf("\n\r"); + libucprintf("--------------------------------------------------------\n\r"); + if(dirent->DIR_Attr&ATTR_READ_ONLY)libucprintf("This entry is read only\n\r"); + if(dirent->DIR_Attr&ATTR_HIDDEN)libucprintf("This entry is hidden\n\r"); + if(dirent->DIR_Attr&ATTR_SYSTEM)libucprintf("This entry is a system file/folder\n\r"); + if(dirent->DIR_Attr&ATTR_VOLUME_ID)libucprintf("This entry is the root entry of the system\n\r"); + if(dirent->DIR_Attr&ATTR_DIRECTORY)libucprintf("This entry is a directory\n\r"); + if(dirent->DIR_Attr&ATTR_ARCHIVE)libucprintf("This entry is an archive\n\r"); + if(dirent->DIR_Attr&ATTR_LONGNAME)libucprintf("This entry is a long name entry\n\r"); + libucprintf("In sector %d\n\r",dirent->CurrentSec); + libucprintf("Entry %d\n\r",dirent->Currententry); + libucprintf("________________________________________________________\n\r"); + return 0; + } + return 1; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/apps/FS_Explorer/fsexplorer.h b/lib/src/apps/FS_Explorer/fsexplorer.h new file mode 100644 --- /dev/null +++ b/lib/src/apps/FS_Explorer/fsexplorer.h @@ -0,0 +1,74 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef FSEXPLORER_H +#define FSEXPLORER_H +#include +#include +#include +#include +#include +#include +#include + +extern int fsexplprintDirentInfos(ucdirent* dirent); +extern int fsexplprintBootSector(blkdevice* dev); +extern int fsexplprintPartInfos(dikpartition* part); +extern int fsexplprintSector(blkdevice* dev,unsigned int sectorIndex); + + + + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/apps/FS_Explorer/fsexplorer.pro b/lib/src/apps/FS_Explorer/fsexplorer.pro new file mode 100644 --- /dev/null +++ b/lib/src/apps/FS_Explorer/fsexplorer.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +lpc17XX.ARCH = lpc17XX-arm-noabi-gcc +lpc17XX.TARGET = libfsexplorer +lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_FSEXPLORER) +lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FSEXPLORER) + +lpc17XX.LIBS += HEXVIEWER ALLFS UCSTRINGS UHANDLE + +lpc17XX.SOURCES += fsexplorer.c + + +lpc17XX.HEADERS += fsexplorer.h + + + +lpc21XX.ARCH = lpc21XX-arm-noabi-gcc +lpc21XX.TARGET = libfsexplorer +lpc21XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_FSEXPLORER) +lpc21XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FSEXPLORER) + +lpc21XX.LIBS += HEXVIEWER ALLFS UCSTRINGS UHANDLE + +lpc21XX.SOURCES += fsexplorer.c + + +lpc21XX.HEADERS += fsexplorer.h diff --git a/lib/src/apps/FS_Explorer/lpc17XX.mk b/lib/src/apps/FS_Explorer/lpc17XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/apps/FS_Explorer/lpc17XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FSEXPLORER) +HEADERS += fsexplorer.h +LIBSOURCES += fsexplorer.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc17XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc +TARGET=libfsexplorer +LIBUC_INCLUDES=$(LIBUC_INC_DIR_HEXVIEWER_CMD) $(LIBUC_INC_DIR_ALLFS_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_HEXVIEWER_CMD) $(LIBUC_LIBS_HEXVIEWER) $(LIBUC_LIBS_DIR_ALLFS_CMD) $(LIBUC_LIBS_ALLFS) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_FSEXPLORER) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_FSEXPLORER) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/apps/FS_Explorer/lpc21XX.mk b/lib/src/apps/FS_Explorer/lpc21XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/apps/FS_Explorer/lpc21XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FSEXPLORER) +HEADERS += fsexplorer.h +LIBSOURCES += fsexplorer.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libfsexplorer +LIBUC_INCLUDES=$(LIBUC_INC_DIR_HEXVIEWER_CMD) $(LIBUC_INC_DIR_ALLFS_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) $(LIBUC_INC_DIR_HEXVIEWER_CMD) $(LIBUC_INC_DIR_ALLFS_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_HEXVIEWER_CMD) $(LIBUC_LIBS_HEXVIEWER) $(LIBUC_LIBS_DIR_ALLFS_CMD) $(LIBUC_LIBS_ALLFS) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) $(LIBUC_LIBS_DIR_HEXVIEWER_CMD) $(LIBUC_LIBS_HEXVIEWER) $(LIBUC_LIBS_DIR_ALLFS_CMD) $(LIBUC_LIBS_ALLFS) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_FSEXPLORER) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_FSEXPLORER) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/apps/Makefile b/lib/src/apps/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/apps/Makefile @@ -0,0 +1,13 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 +include $(LIBUC)/rules/common/rules.mk + +all:subdir + make -C FS_Explorer + @echo Code compiled + +clean: + make clean -C FS_Explorer + @echo Code compiled + diff --git a/lib/src/apps/apps.pro b/lib/src/apps/apps.pro new file mode 100644 --- /dev/null +++ b/lib/src/apps/apps.pro @@ -0,0 +1,2 @@ +TEMPLATE = dir +SUBDIRS += FS_Explorer diff --git a/lib/src/common/24LCXX/24LC0X/24LC0X.c b/lib/src/common/24LCXX/24LC0X/24LC0X.c --- a/lib/src/common/24LCXX/24LC0X/24LC0X.c +++ b/lib/src/common/24LCXX/24LC0X/24LC0X.c @@ -25,14 +25,14 @@ /* struct 24LC0X_str { - i2cDev* iicdev; + i2cDev iicdev; unsigned char devAddress; unsigned char size; }; */ -void eeprom24lc0xopen(eeprom24lc0xDev* dev,i2cDev* iicdev,unsigned char A0_A1_A2_val,unsigned int size) +void eeprom24lc0xopen(eeprom24lc0xDev* dev,i2cDev iicdev,unsigned char A0_A1_A2_val,unsigned int size) { dev->iicdev = iicdev; dev->devAddress = 0x50 | (A0_A1_A2_val & 0x7); diff --git a/lib/src/common/24LCXX/24LC0X/24LC0X.h b/lib/src/common/24LCXX/24LC0X/24LC0X.h --- a/lib/src/common/24LCXX/24LC0X/24LC0X.h +++ b/lib/src/common/24LCXX/24LC0X/24LC0X.h @@ -23,10 +23,11 @@ #define B24LC0X_H #include "iic.h" +#include struct eeprom24LC0X_str { - i2cDev* iicdev; + i2cDev iicdev; unsigned char devAddress; unsigned char size; }; @@ -34,7 +35,7 @@ struct eeprom24LC0X_str typedef struct eeprom24LC0X_str eeprom24lc0xDev; -extern void eeprom24lc0xopen(eeprom24lc0xDev* dev,i2cDev* iicdev,unsigned char A0_A1_A2_val,unsigned int size); +extern void eeprom24lc0xopen(eeprom24lc0xDev* dev,i2cDev iicdev,unsigned char A0_A1_A2_val,unsigned int size); extern void eeprom24lc0xpagewrite(eeprom24lc0xDev dev,unsigned char address,unsigned char* page); extern void eeprom24lc0xpageread(eeprom24lc0xDev dev,unsigned char address,unsigned char* page); diff --git a/lib/src/common/24LCXX/24LC0X/24LC0X.pro b/lib/src/common/24LCXX/24LC0X/24LC0X.pro --- a/lib/src/common/24LCXX/24LC0X/24LC0X.pro +++ b/lib/src/common/24LCXX/24LC0X/24LC0X.pro @@ -5,7 +5,7 @@ lpc17XX.TARGET = lib24lc0X lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_24LC0X) lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_24LC0X) -lpc17XX.LIBS += CORE IIC +lpc17XX.LIBS += CORE IIC UHANDLE lpc17XX.SOURCES += 24LC0X.c diff --git a/lib/src/common/24LCXX/24LC0X/Makefile b/lib/src/common/24LCXX/24LC0X/Makefile --- a/lib/src/common/24LCXX/24LC0X/Makefile +++ b/lib/src/common/24LCXX/24LC0X/Makefile @@ -4,3 +4,6 @@ LIBUC = /opt/libuc2 all: make -f lpc17XX.mk + +clean: + make clean -f lpc17XX.mk diff --git a/lib/src/common/24LCXX/24LC0X/lpc17XX.mk b/lib/src/common/24LCXX/24LC0X/lpc17XX.mk --- a/lib/src/common/24LCXX/24LC0X/lpc17XX.mk +++ b/lib/src/common/24LCXX/24LC0X/lpc17XX.mk @@ -4,12 +4,15 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_INC_DIR_24LC0X) HEADERS += 24LC0X.h LIBSOURCES += 24LC0X.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc17XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc TARGET=lib24lc0X -LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_IIC_CMD) -LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_IIC_CMD) $(LIBUC_LIBS_IIC) +LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_IIC_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_IIC_CMD) $(LIBUC_LIBS_IIC) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_24LC0X) HEADERSINSTALLPATH=$(LIBUC_INC_DIR_24LC0X) BSP=generic @@ -17,3 +20,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/Makefile b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/Makefile @@ -0,0 +1,11 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +all: + make -f lpc17XX.mk + make -f lpc21XX.mk + +clean: + make clean -f lpc17XX.mk + make clean -f lpc21XX.mk diff --git a/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/blkdevice.c b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/blkdevice.c new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/blkdevice.c @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ + +#include "blkdevice.h" diff --git a/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/blkdevice.h b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/blkdevice.h new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/blkdevice.h @@ -0,0 +1,128 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef BLKDEVICE_H +#define BLKDEVICE_H +#include +/* Disk Status Bits (DSTATUS) */ + +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl fucntion */ +/* Generic ioctl command (defined for FatFs) */ +#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ +#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ +#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ + +/* Generic ioctl command */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ + +/* NAND specific ioctl command */ +#define NAND_FORMAT 30 /* Create physical format */ + +/* Status of Disk Functions */ +typedef unsigned char DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + +typedef volatile struct blkdevice_str blkdevice; + +typedef void (*blkdevselect_t)(char); +typedef void (*blkdevpower_t)(char) ; +typedef char (*blkdevdetect_t)() ; +typedef char (*blkdevwriteprotected_t)() ; +typedef DRESULT (*blkdevwrite_t)(blkdevice* _this,const char *buff,unsigned long sector,char count) ; +typedef DRESULT (*blkdevread_t)(blkdevice* _this,char *buff,unsigned long sector,char count) ; +typedef DRESULT (*blkdevioctl_t)(blkdevice* _this,char ctrl,void *buff) ; +typedef DSTATUS (*blkdevinitialize_t)(blkdevice* _this) ; +typedef DSTATUS (*blkdevstatus_t) (blkdevice* _this) ; + +struct blkdevice_str +{ + UHANDLE phy; + unsigned int size; + unsigned int MaxSpeed; + unsigned char Version; + blkdevselect_t select; + blkdevpower_t power; + blkdevdetect_t detect; + blkdevwriteprotected_t writeprotected; + blkdevwrite_t write; + blkdevread_t read; + blkdevioctl_t ioctl; + blkdevinitialize_t initialize; + blkdevstatus_t status; +}; + + + + + + +#endif + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/blkdevice.pro b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/blkdevice.pro new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/blkdevice.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +lpc17XX.ARCH = lpc17XX-arm-noabi-gcc +lpc17XX.TARGET = libblkdevice +lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_BLKDEVICE) +lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_BLKDEVICE) + +lpc17XX.LIBS += UHANDLE + +lpc17XX.SOURCES += blkdevice.c + + +lpc17XX.HEADERS += blkdevice.h + + + +lpc21XX.ARCH = lpc21XX-arm-noabi-gcc +lpc21XX.TARGET = libblkdevice +lpc21XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_BLKDEVICE) +lpc21XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_BLKDEVICE) + +lpc21XX.LIBS += UHANDLE + +lpc21XX.SOURCES += blkdevice.c + + +lpc21XX.HEADERS += blkdevice.h diff --git a/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/lpc17XX.mk b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/lpc17XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/lpc17XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_BLKDEVICE) +HEADERS += blkdevice.h +LIBSOURCES += blkdevice.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc17XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc +TARGET=libblkdevice +LIBUC_INCLUDES=$(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_BLKDEVICE) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_BLKDEVICE) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/lpc21XX.mk b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/lpc21XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/BLOCKDEVICES/lpc21XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_BLKDEVICE) +HEADERS += blkdevice.h +LIBSOURCES += blkdevice.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libblkdevice +LIBUC_INCLUDES=$(LIBUC_INC_DIR_UHANDLE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_BLKDEVICE) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_BLKDEVICE) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/DIRENT/Makefile b/lib/src/common/FILE_SYSTEM/DIRENT/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/DIRENT/Makefile @@ -0,0 +1,11 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +all: + make -f lpc17XX.mk + make -f lpc21XX.mk + +clean: + make clean -f lpc17XX.mk + make clean -f lpc21XX.mk diff --git a/lib/src/common/FILE_SYSTEM/DIRENT/lpc17XX.mk b/lib/src/common/FILE_SYSTEM/DIRENT/lpc17XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/DIRENT/lpc17XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_UCDIRENT) +HEADERS += ucdirent.h +LIBSOURCES += ucdirent.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc17XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc +TARGET=libucdirent +LIBUC_INCLUDES=$(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_UCDIRENT) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_UCDIRENT) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/DIRENT/lpc21XX.mk b/lib/src/common/FILE_SYSTEM/DIRENT/lpc21XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/DIRENT/lpc21XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_UCDIRENT) +HEADERS += ucdirent.h +LIBSOURCES += ucdirent.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libucdirent +LIBUC_INCLUDES=$(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) $(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) $(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_UCDIRENT) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_UCDIRENT) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/DIRENT/ucdirent.c b/lib/src/common/FILE_SYSTEM/DIRENT/ucdirent.c new file mode 100644 diff --git a/lib/src/common/FILE_SYSTEM/DIRENT/ucdirent.h b/lib/src/common/FILE_SYSTEM/DIRENT/ucdirent.h new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/DIRENT/ucdirent.h @@ -0,0 +1,110 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef UCDIRENT_H +#define UCDIRENT_H +#include +#include +//#include + +#define ATTR_READ_ONLY 0x01 +#define ATTR_HIDDEN 0x02 +#define ATTR_SYSTEM 0x04 +#define ATTR_VOLUME_ID 0x08 +#define ATTR_DIRECTORY 0x10 +#define ATTR_ARCHIVE 0x20 +#define ATTR_LONGNAME 0x0F + +#define DIRENT_EndOfDir 1 +#define DIRENT_BabArg 2 +#define DIRENT_ReadErr 3 +#define DIRENT_LastSect 4 +#define DIRENT_BadSect 5 +#define DIRENT_noErr 0 + +typedef struct dirent_str ucdirent; +typedef int (*getrootfirstent_t)(ucdirent* entry); +typedef int (*nextdirent_t)(ucdirent* entry); + + +struct dirent_str +{ + unsigned char DIR_Name[16]; + unsigned char DIR_Attr; + unsigned char DIR_CrtTimeTenth; + unsigned short DIR_CrtTime; + unsigned short DIR_CrtDate; + unsigned short DIR_LstAccDate; + unsigned short DIR_FstClusHI; + unsigned short DIR_WrtTime; + unsigned short DIR_WrtDate; + unsigned short DIR_FstClustLO; + unsigned int DIR_FileSize; + unsigned int CurrentSec; + unsigned char Currententry; + UHANDLE fs; + getrootfirstent_t getrootfirstent; + nextdirent_t nextdirent; +}; + + +#define direntgetroot(dirent) (dirent).getrootfirstent(&dirent) +#define direntgetnext(dirent) (dirent).nextdirent(&dirent) + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/FILE_SYSTEM/DIRENT/ucdirent.pro b/lib/src/common/FILE_SYSTEM/DIRENT/ucdirent.pro new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/DIRENT/ucdirent.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +lpc17XX.ARCH = lpc17XX-arm-noabi-gcc +lpc17XX.TARGET = libucdirent +lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_UCDIRENT) +lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_UCDIRENT) + +lpc17XX.LIBS += BLKDEVICE UCSTRINGS UHANDLE + +lpc17XX.SOURCES += ucdirent.c + + +lpc17XX.HEADERS += ucdirent.h + + + +lpc21XX.ARCH = lpc21XX-arm-noabi-gcc +lpc21XX.TARGET = libucdirent +lpc21XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_UCDIRENT) +lpc21XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_UCDIRENT) + +lpc21XX.LIBS += BLKDEVICE UCSTRINGS UHANDLE + +lpc21XX.SOURCES += ucdirent.c + + +lpc21XX.HEADERS += ucdirent.h diff --git a/lib/src/common/FILE_SYSTEM/FAT32/Makefile b/lib/src/common/FILE_SYSTEM/FAT32/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FAT32/Makefile @@ -0,0 +1,11 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +all: + make -f lpc17XX.mk + make -f lpc21XX.mk + +clean: + make clean -f lpc17XX.mk + make clean -f lpc21XX.mk diff --git a/lib/src/common/FILE_SYSTEM/FAT32/fat32.c b/lib/src/common/FILE_SYSTEM/FAT32/fat32.c new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FAT32/fat32.c @@ -0,0 +1,176 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#include "fat32.h" +#include "libucstrings.h" + +char fat32buff[512]; +unsigned int lastSecAddrs=-1; +FAT32fs* lastFATFS=0; + +int fat32open(FAT32fs* fs,dikpartition* part) +{ + char sector[512]; + fs->part = part; + if(!isFat32(fs->part->TypeCode))return FATBadpart; + if(fs->part->phy->read(fs->part->phy,sector,fs->part->LBABegin,1)!=RES_OK)return FATReadErr; + fs->BPB_BytsPerSec = sector[BPB_BytsPerSecoff] + (sector[BPB_BytsPerSecoff+1]<<8); + fs->BPB_RsvdSecCnt = sector[BPB_RsvdSecCntoff] + (sector[BPB_RsvdSecCntoff+1]<<8); + fs->BPB_FATSz32 = sector[BPB_FATSz32off] + (sector[BPB_FATSz32off+1]<<8) + (sector[BPB_FATSz32off+2]<<16) + (sector[BPB_FATSz32off+3]<<24); + fs->BPB_RootClus = sector[BPB_RootClusoff] + (sector[BPB_RootClusoff+1]<<8) + (sector[BPB_RootClusoff+2]<<16) + (sector[BPB_RootClusoff+3]<<24); + fs->BPB_SecPerClus = sector[BPB_SecPerClusoff]; + fs->BPB_NumFATs = sector[BPB_NumFATsoff]; + fs->fat_begin_lba = (unsigned int)fs->part->LBABegin + (unsigned int)(unsigned short)fs->BPB_RsvdSecCnt; + fs->cluster_begin_lba = (unsigned int)fs->fat_begin_lba + ((unsigned int)fs->BPB_NumFATs * (unsigned int)fs->BPB_FATSz32 ); + return FATnoErr; +} + +int fat32mkdirent(FAT32fs* fs,ucdirent* dirent) +{ + if(fs==0) return DIRENT_BabArg; + if(dirent==0) return DIRENT_BabArg; + dirent->fs = (UHANDLE)fs; + dirent->getrootfirstent = &fat32getrootfirstent; + dirent->nextdirent = &fat32nextdirent; + return DIRENT_noErr; +} + + +int fat32getrootfirstent(ucdirent* entry) +{ + entry->CurrentSec = ((FAT32fs*)entry->fs)->cluster_begin_lba; + entry->Currententry = -1; + return fat32nextdirent(entry); +} + + +int fat32nextdirent(ucdirent* entry) +{ + int n=0,res=DIRENT_noErr,k,j; + k=(((signed char)entry->Currententry)+1)*32; /*Restart at last dir entry*/ + j=entry->CurrentSec;//-((FAT32fs*)entry->fs)->cluster_begin_lba; /*Restart at last sector*/ + do + { + if((lastSecAddrs!=j) || (lastFATFS!=((FAT32fs*)entry->fs))) + { + if(((FAT32fs*)entry->fs)->part->phy->read(((FAT32fs*)entry->fs)->part->phy,fat32buff,j,1)!=RES_OK) + { + return DIRENT_ReadErr; + } + } + for(k=k;k<(512);k+=32) /*512 Bytes per sector and 32 bytes per entry*/ + { + if(fat32buff[DIR_Nameoff+k]!=0xE5) /*0xE5 = free entry*/ + { + if(fat32buff[DIR_Nameoff+k]==0) return DIRENT_EndOfDir; /*0x00 = end of dir*/ + else + if(fat32buff[DIR_Attroff + k]!=ATTR_LONGNAME) + { + for(n=0;n<11;n++)entry->DIR_Name[n] = fat32buff[n+DIR_Nameoff + k]; + entry->DIR_Attr = fat32buff[DIR_Attroff + k]; + entry->DIR_CrtTimeTenth = fat32buff[DIR_CrtTimeTenthoff + k]; + entry->DIR_CrtTime = fat32buff[DIR_CrtTimeoff + k] + (fat32buff[DIR_CrtTimeoff+1 + k]<<8); + entry->DIR_CrtDate = fat32buff[DIR_CrtDateoff + k] + (fat32buff[DIR_CrtDateoff+1 + k]<<8); + entry->DIR_LstAccDate = fat32buff[DIR_LstAccDateoff + k] + (fat32buff[DIR_LstAccDateoff+1 + k]<<8); + entry->DIR_FstClusHI = fat32buff[DIR_FstClusHIoff + k] + (fat32buff[DIR_FstClusHIoff+1 + k]<<8); + entry->DIR_WrtTime = fat32buff[DIR_WrtTimeoff + k] + (fat32buff[DIR_WrtTimeoff+1 + k]<<8); + entry->DIR_FstClustLO = fat32buff[DIR_FstClusLOoff + k] + (fat32buff[DIR_FstClusLOoff+1 + k]<<8); + entry->DIR_FileSize = fat32buff[DIR_FileSizeoff + k] + (fat32buff[DIR_FileSizeoff+1 + k]<<8) + (fat32buff[DIR_FileSizeoff+2 + k]<<16) + (fat32buff[DIR_FileSizeoff+3 + k]<<24); + entry->CurrentSec = j; + entry->Currententry = (unsigned char)(k/32); + return DIRENT_noErr; + } + } + + } + j=fat32nextsectorlba(((FAT32fs*)entry->fs),j,&k); + if(j!=DIRENT_noErr) + { + if(j==DIRENT_LastSect) return DIRENT_EndOfDir; /*Not clean but can avoid some bugs*/ + return j; + } + j=k; + k=0; + }while(res==DIRENT_noErr); + return res; +} + + + +unsigned int fat32getdirentlba(ucdirent* entry) +{ + unsigned int culsterNum = (unsigned int)((unsigned short)entry->DIR_FstClustLO) + ((unsigned int)((unsigned short)entry->DIR_FstClusHI) <<16); + unsigned int lba=clusterlba(((FAT32fs*)entry->fs),culsterNum); + return lba; +} + +int fat32nextsectorlba(FAT32fs* fs,unsigned int lastsector_lba,unsigned int* nextsector_lba) +{ + + if((lastsector_lba + 1 - fs->cluster_begin_lba & (fs->BPB_SecPerClus-1))!=0) /*Is it the last sector of the cluster?*/ + { + *nextsector_lba = lastsector_lba+1; + libucprintf("Next sector is %x\n\r",*nextsector_lba); + return DIRENT_noErr; + } + int clusternum=fat32sectorlbatoclusternum(fs,lastsector_lba); /*Get cluster Number from sector number*/ + int fatsec=fat32clusterinfatsect(fs,clusternum); /*Get FAT sector number*/ + if((lastSecAddrs!=fatsec) || (lastFATFS!=fs)) /*Check if sector already buffered*/ + { + if(fs->part->phy->read(fs->part->phy,fat32buff,fatsec,1)!=RES_OK) + { + return DIRENT_ReadErr; + } + } + lastSecAddrs=fatsec; + lastFATFS=fs; + char i= fat32clusterinfatoff(clusternum); + *nextsector_lba = fat32buff[i] + (fat32buff[i+1]<<8) + (fat32buff[i+2]<<16) + (fat32buff[i+3]<<24); + if(*nextsector_lba>=0xFFFFFFF8)return DIRENT_LastSect; + if(*nextsector_lba==0xFFFFFFF7)return DIRENT_BadSect; + *nextsector_lba = clusterlba(fs,*nextsector_lba); + return DIRENT_noErr; +} + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/FILE_SYSTEM/FAT32/fat32.h b/lib/src/common/FILE_SYSTEM/FAT32/fat32.h new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FAT32/fat32.h @@ -0,0 +1,139 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef FAT32_H +#define FAT32_H +#include +#include +#include +/*BPB (Boot Sector) Offsets */ + +#define BS_jmpBootoff 0 +#define BS_OEMNameoff 3 +#define BPB_BytsPerSecoff 11 +#define BPB_SecPerClusoff 13 +#define BPB_RsvdSecCntoff 14 +#define BPB_NumFATsoff 16 +#define BPB_RootEntCntoff 17 +#define BPB_TotSec16off 19 +#define BPB_Mediaoff 21 +#define BPB_FATSz16off 22 +#define BPB_SecPerTrkoff 24 +#define BPB_NumHeadsoff 26 +#define BPB_HiddSecoff 28 +#define BPB_TotSec32off 32 +/*FAT16*/ +#define BS_DrvNumFAT16off 36 +#define BS_Reserved1FAT16off 37 +#define BS_BootSigFAT16off 38 +#define BS_VolIDFAT16off 39 +#define BS_VolLabFAT16off 43 +#define BS_FilSysTypeFAT16off 54 +/*FAT32*/ +#define BPB_FATSz32off 36 +#define BPB_ExtFlagsoff 40 +#define BPB_FSVeroff 42 +#define BPB_RootClusoff 44 +#define BPB_FSInfooff 48 +#define BPB_BkBootSecoff 50 +#define BPB_Reservedoff 52 +#define BS_DrvNumFAT32off 64 +#define BS_Reserved1FAT32off 65 +#define BS_BootSigFAT32off 66 +#define BS_VolIDFAT32off 67 +#define BS_VolLabFAT32off 71 +#define BS_FilSysTypeFAT32off 82 + + +#define DIR_Nameoff 0 +#define DIR_Attroff 0xb +#define DIR_FstClusHIoff 0x14 +#define DIR_FstClusLOoff 0x1A +#define DIR_FileSizeoff 0x1c +#define DIR_CrtTimeTenthoff 13 +#define DIR_CrtTimeoff 14 +#define DIR_CrtDateoff 16 +#define DIR_LstAccDateoff 18 +#define DIR_WrtTimeoff 22 +#define DIR_WrtDateoff 24 + + + +#define FATBadpart 1 +#define FATBabArg 2 +#define FATReadErr 3 +#define FATnoErr 0 + +struct FAT32part_str +{ + unsigned short BPB_BytsPerSec; + unsigned short BPB_RsvdSecCnt; + unsigned int BPB_FATSz32; + unsigned int BPB_RootClus; + unsigned int fat_begin_lba; + unsigned int cluster_begin_lba; + unsigned char BPB_SecPerClus; + unsigned char BPB_NumFATs; + dikpartition* part; +}; + +typedef volatile struct FAT32part_str FAT32fs; + +#define clusterlba(fs,cluster_number) ((unsigned int)fs->cluster_begin_lba + (((unsigned int)cluster_number) - (2)) * (unsigned int)fs->BPB_SecPerClus) +#define fat32clusterinfatsect(fs,cluster_number) ((((unsigned int)(cluster_number))>>6) + fs->fat_begin_lba) +#define fat32clusterinfatoff(cluster_number) (((cluster_number)&0x3F)*4) +#define fat32sectorlbatoclusternum(fs,sectorlba) ((((((unsigned int)sectorlba & (-1^(fs->BPB_SecPerClus-1))))-((unsigned int)fs->cluster_begin_lba))/(unsigned int)fs->BPB_SecPerClus)+(2)) + +extern int fat32open(FAT32fs* fs,dikpartition* part); +extern int fat32mkdirent(FAT32fs* fs,ucdirent* dirent); + +extern int fat32getrootfirstent(ucdirent* entry); +extern int fat32nextdirent(ucdirent* entry); +extern int fat32nextsectorlba(FAT32fs* fs,unsigned int lastsector_lba,unsigned int* nextsector_lba); +extern unsigned int fat32getdirentlba(ucdirent* entry); + + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/FILE_SYSTEM/FAT32/fat32.pro b/lib/src/common/FILE_SYSTEM/FAT32/fat32.pro new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FAT32/fat32.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +lpc17XX.ARCH = lpc17XX-arm-noabi-gcc +lpc17XX.TARGET = libfat32 +lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_FAT32) +lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FAT32) + +lpc17XX.LIBS += BLKDEVICE MBR UCSTRINGS UHANDLE FS UCDIRENT + +lpc17XX.SOURCES += fat32.c + + +lpc17XX.HEADERS += fat32.h + + + +lpc21XX.ARCH = lpc21XX-arm-noabi-gcc +lpc21XX.TARGET = libfat32 +lpc21XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_FAT32) +lpc21XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FAT32) + +lpc21XX.LIBS += BLKDEVICE MBR UCSTRINGS UHANDLE FS UCDIRENT + +lpc21XX.SOURCES += fat32.c + + +lpc21XX.HEADERS += fat32.h diff --git a/lib/src/common/FILE_SYSTEM/FAT32/lpc17XX.mk b/lib/src/common/FILE_SYSTEM/FAT32/lpc17XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FAT32/lpc17XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FAT32) +HEADERS += fat32.h +LIBSOURCES += fat32.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc17XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc +TARGET=libfat32 +LIBUC_INCLUDES=$(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_MBR_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) $(LIBUC_INC_DIR_FS_CMD) $(LIBUC_INC_DIR_UCDIRENT_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_MBR_CMD) $(LIBUC_LIBS_MBR) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) $(LIBUC_LIBS_DIR_FS_CMD) $(LIBUC_LIBS_FS) $(LIBUC_LIBS_DIR_UCDIRENT_CMD) $(LIBUC_LIBS_UCDIRENT) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_FAT32) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_FAT32) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/FAT32/lpc21XX.mk b/lib/src/common/FILE_SYSTEM/FAT32/lpc21XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FAT32/lpc21XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FAT32) +HEADERS += fat32.h +LIBSOURCES += fat32.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libfat32 +LIBUC_INCLUDES=$(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_MBR_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) $(LIBUC_INC_DIR_FS_CMD) $(LIBUC_INC_DIR_UCDIRENT_CMD) $(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_MBR_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) $(LIBUC_INC_DIR_FS_CMD) $(LIBUC_INC_DIR_UCDIRENT_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_MBR_CMD) $(LIBUC_LIBS_MBR) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) $(LIBUC_LIBS_DIR_FS_CMD) $(LIBUC_LIBS_FS) $(LIBUC_LIBS_DIR_UCDIRENT_CMD) $(LIBUC_LIBS_UCDIRENT) $(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_MBR_CMD) $(LIBUC_LIBS_MBR) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) $(LIBUC_LIBS_DIR_FS_CMD) $(LIBUC_LIBS_FS) $(LIBUC_LIBS_DIR_UCDIRENT_CMD) $(LIBUC_LIBS_UCDIRENT) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_FAT32) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_FAT32) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/FILE_SYSTEM.pro b/lib/src/common/FILE_SYSTEM/FILE_SYSTEM.pro new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FILE_SYSTEM.pro @@ -0,0 +1,7 @@ +TEMPLATE = dir +SUBDIRS += BLOCKDEVICES \ + SDCARD \ + MBR \ + FS \ + DIRENT \ + FAT32 diff --git a/lib/src/common/FILE_SYSTEM/FS/Makefile b/lib/src/common/FILE_SYSTEM/FS/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FS/Makefile @@ -0,0 +1,11 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +all: + make -f lpc17XX.mk + make -f lpc21XX.mk + +clean: + make clean -f lpc17XX.mk + make clean -f lpc21XX.mk diff --git a/lib/src/common/FILE_SYSTEM/FS/fs.c b/lib/src/common/FILE_SYSTEM/FS/fs.c new file mode 100644 diff --git a/lib/src/common/FILE_SYSTEM/FS/fs.h b/lib/src/common/FILE_SYSTEM/FS/fs.h new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FS/fs.h @@ -0,0 +1,78 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef FS_H +#define FS_H +#include +#include + +struct fs_str +{ + UHANDLE fat; +}; + +typedef struct fs_str filesys_t; + + + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/FILE_SYSTEM/FS/fs.pro b/lib/src/common/FILE_SYSTEM/FS/fs.pro new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FS/fs.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +lpc17XX.ARCH = lpc17XX-arm-noabi-gcc +lpc17XX.TARGET = libfs +lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_FS) +lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FS) + +lpc17XX.LIBS += BLKDEVICE UHANDLE + +lpc17XX.SOURCES += fs.c + + +lpc17XX.HEADERS += fs.h + + + +lpc21XX.ARCH = lpc21XX-arm-noabi-gcc +lpc21XX.TARGET = libfs +lpc21XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_FS) +lpc21XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FS) + +lpc21XX.LIBS += BLKDEVICE UHANDLE + +lpc21XX.SOURCES += fs.c + + +lpc21XX.HEADERS += fs.h diff --git a/lib/src/common/FILE_SYSTEM/FS/lpc17XX.mk b/lib/src/common/FILE_SYSTEM/FS/lpc17XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FS/lpc17XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FS) +HEADERS += fs.h +LIBSOURCES += fs.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc17XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc +TARGET=libfs +LIBUC_INCLUDES=$(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_FS) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_FS) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/FS/lpc21XX.mk b/lib/src/common/FILE_SYSTEM/FS/lpc21XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/FS/lpc21XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FS) +HEADERS += fs.h +LIBSOURCES += fs.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libfs +LIBUC_INCLUDES=$(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) $(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) $(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_FS) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_FS) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/MBR/MBR.pro b/lib/src/common/FILE_SYSTEM/MBR/MBR.pro new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/MBR/MBR.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +lpc17XX.ARCH = lpc17XX-arm-noabi-gcc +lpc17XX.TARGET = libmbr +lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_MBR) +lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_MBR) + +lpc17XX.LIBS += BLKDEVICE UCSTRINGS UHANDLE + +lpc17XX.SOURCES += mbr.c + + +lpc17XX.HEADERS += mbr.h + + + +lpc21XX.ARCH = lpc21XX-arm-noabi-gcc +lpc21XX.TARGET = libmbr +lpc21XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_MBR) +lpc21XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_MBR) + +lpc21XX.LIBS += BLKDEVICE UCSTRINGS UHANDLE + +lpc21XX.SOURCES += mbr.c + + +lpc21XX.HEADERS += mbr.h diff --git a/lib/src/common/FILE_SYSTEM/MBR/Makefile b/lib/src/common/FILE_SYSTEM/MBR/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/MBR/Makefile @@ -0,0 +1,11 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +all: + make -f lpc17XX.mk + make -f lpc21XX.mk + +clean: + make clean -f lpc17XX.mk + make clean -f lpc21XX.mk diff --git a/lib/src/common/FILE_SYSTEM/MBR/lpc17XX.mk b/lib/src/common/FILE_SYSTEM/MBR/lpc17XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/MBR/lpc17XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_MBR) +HEADERS += mbr.h +LIBSOURCES += mbr.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc17XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc +TARGET=libmbr +LIBUC_INCLUDES=$(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_MBR) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_MBR) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/MBR/lpc21XX.mk b/lib/src/common/FILE_SYSTEM/MBR/lpc21XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/MBR/lpc21XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_MBR) +HEADERS += mbr.h +LIBSOURCES += mbr.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libmbr +LIBUC_INCLUDES=$(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) $(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) $(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_MBR) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_MBR) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/MBR/mbr.c b/lib/src/common/FILE_SYSTEM/MBR/mbr.c new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/MBR/mbr.c @@ -0,0 +1,70 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#include "mbr.h" + + +int mbropen(blkdevice* phy,dikpartition* part,char partNum) +{ + char mbr[512]; + if((part==0) || (phy ==0) || (partNum>4) || (partNum==0) ) return MBRBabArg; + part->phy = phy; + if(phy->read(phy,mbr,0,1)!=RES_OK)return MBRReadErr; + if((mbr[510] != 0x55) || (mbr[511] != 0xAA)) return MBRBadMbr; + part->TypeCode = mbr[(512-82+TypeCodeoffset)+partNum*16]; + part->LBABegin = (unsigned int)mbr[(512-82+LBABeginoffset)+partNum*16] + ((unsigned int)mbr[(512-82+LBABeginoffset+1)+partNum*16]<<8)+ ((unsigned int)mbr[(512-82+LBABeginoffset+2)+partNum*16]<<16)+ ((unsigned int)mbr[(512-82+LBABeginoffset+3)+partNum*16]<<24); + part->NumOfSec = (unsigned int)mbr[(512-82+NumOfSecoffset)+partNum*16] + ((unsigned int)mbr[(512-82+NumOfSecoffset+1)+partNum*16]<<8)+ ((unsigned int)mbr[(512-82+NumOfSecoffset+2)+partNum*16]<<16)+ ((unsigned int)mbr[(512-82+NumOfSecoffset+3)+partNum*16]<<24); + return MBRnoErr; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/FILE_SYSTEM/MBR/mbr.h b/lib/src/common/FILE_SYSTEM/MBR/mbr.h new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/MBR/mbr.h @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef MBR_H +#define MBR_H +#include +#include + +#define BootFlagoffset 0 +#define TypeCodeoffset 4 +#define LBABeginoffset 8 +#define NumOfSecoffset 12 + +#define MBRBadMbr 1 +#define MBRBabArg 2 +#define MBRReadErr 3 +#define MBRnoErr 0 + +#define isFat32(TypeCode) (((TypeCode)==0x0b)||((TypeCode)==0x0c)) + +struct MBRpartition +{ + char TypeCode; + unsigned int LBABegin; + unsigned int NumOfSec; + blkdevice* phy; +}; + +typedef struct MBRpartition dikpartition; + + +int mbropen(blkdevice* phy,dikpartition* part,char partNum); + + +#endif + + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/FILE_SYSTEM/Makefile b/lib/src/common/FILE_SYSTEM/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/Makefile @@ -0,0 +1,23 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 +include $(LIBUC)/rules/common/rules.mk + +all:subdir + make -C BLOCKDEVICES + make -C SDCARD + make -C MBR + make -C FS + make -C DIRENT + make -C FAT32 + @echo Code compiled + +clean: + make clean -C BLOCKDEVICES + make clean -C SDCARD + make clean -C MBR + make clean -C FS + make clean -C DIRENT + make clean -C FAT32 + @echo Code compiled + diff --git a/lib/src/common/FILE_SYSTEM/SDCARD/Makefile b/lib/src/common/FILE_SYSTEM/SDCARD/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/SDCARD/Makefile @@ -0,0 +1,11 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +all: + make -f lpc17XX.mk + make -f lpc21XX.mk + +clean: + make clean -f lpc17XX.mk + make clean -f lpc21XX.mk diff --git a/lib/src/common/FILE_SYSTEM/SDCARD/lpc17XX.mk b/lib/src/common/FILE_SYSTEM/SDCARD/lpc17XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/SDCARD/lpc17XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_SDCARD) +HEADERS += sdcard.h +LIBSOURCES += sdcard.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc17XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc +TARGET=libsdcard +LIBUC_INCLUDES=$(LIBUC_INC_DIR_SSP_CMD) $(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_SSP_CMD) $(LIBUC_LIBS_SSP) $(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_SDCARD) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_SDCARD) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/SDCARD/lpc21XX.mk b/lib/src/common/FILE_SYSTEM/SDCARD/lpc21XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/SDCARD/lpc21XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_SDCARD) +HEADERS += sdcard.h +LIBSOURCES += sdcard.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libsdcard +LIBUC_INCLUDES=$(LIBUC_INC_DIR_SSP_CMD) $(LIBUC_INC_DIR_BLKDEVICE_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) $(LIBUC_INC_DIR_SSP_CMD) $(LIBUC_INC_DIR_BLKDEVICE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_SSP_CMD) $(LIBUC_LIBS_SSP) $(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) $(LIBUC_LIBS_DIR_SSP_CMD) $(LIBUC_LIBS_SSP) $(LIBUC_LIBS_DIR_BLKDEVICE_CMD) $(LIBUC_LIBS_BLKDEVICE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_SDCARD) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_SDCARD) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/FILE_SYSTEM/SDCARD/sdcard.c b/lib/src/common/FILE_SYSTEM/SDCARD/sdcard.c new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/SDCARD/sdcard.c @@ -0,0 +1,482 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#include "sdcard.h" +static volatile +unsigned int Timer1, Timer2; /* 1kHz decrement timer stopped at zero (disk_timerproc()) */ + +void sdcarddeselect (blkdevice* _this) +{ + char d; + _this->select(0); + ((sdcardDev*)_this->phy)->rcvr_mmc(((sdcardDev*)_this->phy)->phy,&d, 1); /* Dummy clock (force DO hi-z for multiple slave SPI) */ +} + +int sdcardselect (blkdevice* _this) /* 1:OK, 0:Timeout */ +{ + char d; + _this->select(1); + ((sdcardDev*)_this->phy)->rcvr_mmc(((sdcardDev*)_this->phy)->phy,&d, 1); /* Dummy clock (force DO enabled) */ + + if (sdcardwait_ready(((sdcardDev*)_this->phy))) return 1; /* OK */ + _this->select(0); + return 0; /* Timeout */ +} + +int sdcardwait_ready (sdcardDev* sdcard) /* 1:OK, 0:Timeout */ +{ + char d; + unsigned int tmr; + volatile unsigned int i=0; + + for (tmr = 100000; tmr; tmr--) { /* Wait for ready in timeout of 500ms */ + sdcard->rcvr_mmc(sdcard->phy,&d, 1); + if (d == 0xFF) break; + for(i=0;i<128;i++); + } + + return tmr ? 1 : 0; +} + +int sdcardrcvr_datablock (sdcardDev* sdcard,char *buff,unsigned int btr) +{ + char d[2]; + unsigned int tmr; + volatile unsigned int i=0; + for (tmr = 50000; tmr; tmr--) { /* Wait for data packet in timeout of 100ms */ + sdcard->rcvr_mmc(sdcard->phy,d, 1); + if (d[0] != 0xFF) break; + for(i=0;i<64;i++); + } + if (d[0] != 0xFE) return 0; /* If not valid data token, return with error */ + + sdcard->rcvr_mmc(sdcard->phy,buff, btr); /* Receive the data block into buffer */ + sdcard->rcvr_mmc(sdcard->phy,d, 2); /* Discard CRC */ + + return 1; /* Return with success */ +} + + +int sdcardxmit_datablock (sdcardDev* sdcard,const char *buff,char token) +{ + char d[2]; + + + if (!sdcardwait_ready(sdcard)) return 0; + + d[0] = token; + sdcard->xmit_mmc(sdcard->phy,d, 1); /* Xmit a token */ + if (token != 0xFD) { /* Is it data token? */ + sdcard->xmit_mmc(sdcard->phy,buff, 512); /* Xmit the 512 byte data block to MMC */ + sdcard->rcvr_mmc(sdcard->phy,d, 2); /* Xmit dummy CRC (0xFF,0xFF) */ + sdcard->rcvr_mmc(sdcard->phy,d, 1); /* Receive data response */ + if ((d[0] & 0x1F) != 0x05) /* If not accepted, return with error */ + return 0; + } + + return 1; +} + + +char sdcardsend_cmd (blkdevice* _this,char cmd,unsigned int arg) +{ + char n, d, buf[6]; + + + if (cmd & 0x80) { /* ACMD is the command sequense of CMD55-CMD */ + cmd &= 0x7F; + n = sdcardsend_cmd(_this,CMD55, 0); + if (n > 1) return n; + } + /* Select the card and wait for ready */ + sdcarddeselect(_this); + if (!sdcardselect(_this)) return 0xFF; + /* Send a command packet */ + buf[0] = 0x40 | cmd; /* Start + Command index */ + buf[1] = (char)(arg >> 24); /* Argument[31..24] */ + buf[2] = (char)(arg >> 16); /* Argument[23..16] */ + buf[3] = (char)(arg >> 8); /* Argument[15..8] */ + buf[4] = (char)arg; /* Argument[7..0] */ + n = 0x01; /* Dummy CRC + Stop */ + if (cmd == CMD0) n = 0x95; /* (valid CRC for CMD0(0)) */ + if (cmd == CMD8) n = 0x87; /* (valid CRC for CMD8(0x1AA)) */ + if (cmd == CMD55) n = 0x63; + buf[5] = n; + ((sdcardDev*)_this->phy)->xmit_mmc(((sdcardDev*)_this->phy)->phy,buf, 6); + /* Receive command response */ + if (cmd == CMD12) {((sdcardDev*)_this->phy)->rcvr_mmc(((sdcardDev*)_this->phy)->phy,&d, 1);} /* Skip a stuff byte when stop reading */ + n = 10; /* Wait for a valid response in timeout of 10 attempts */ + do + { + ((sdcardDev*)_this->phy)->rcvr_mmc(((sdcardDev*)_this->phy)->phy,&d, 1); + //libucprintf("resp=%d\n\r",d); + } + while ((d & 0x80) && --n); + + return d; /* Return with the response value */ +} + + + + +DSTATUS sdcarddisk_status (blkdevice* _this) +{ + DSTATUS s = ((sdcardDev*)_this->phy)->Stat; + char ocr[4]; + + + if ((_this==0) || !_this->detect()) { + s = STA_NODISK | STA_NOINIT; + } else { + s &= ~STA_NODISK; + if (_this->writeprotected()) /* Check card write protection */ + s |= STA_PROTECT; + else + s &= ~STA_PROTECT; + if (!(s & STA_NOINIT)) { + if (sdcardsend_cmd(_this,CMD58, 0)) /* Check if the card is kept initialized */ + s |= STA_NOINIT; + ((sdcardDev*)_this->phy)->rcvr_mmc(((sdcardDev*)_this->phy)->phy,ocr, 4); + _this->select(0); + } + } + ((sdcardDev*)_this->phy)->Stat = s; + + return s; +} + + + + +DSTATUS sdcarddisk_initialize (blkdevice* _this) +{ + char n, cmd, ty, ocr[4],ocr2[4]; + const unsigned char dummy=0xff; + unsigned int speed = 1000000; + + ((sdcardDev*)_this->phy)->setspeed(((sdcardDev*)_this->phy)->phy,350000); + if (_this==0) return STA_NOINIT; /* Supports only drive 0 */ + if (((sdcardDev*)_this->phy)->Stat & STA_NODISK) return ((sdcardDev*)_this->phy)->Stat; /* Is card existing in the soket? */ + + for (n = 10; n; n--) ((sdcardDev*)_this->phy)->xmit_mmc(((sdcardDev*)_this->phy)->phy,&dummy, 1); /* Send 80 dummy clocks */ + + ty = 0; + if (sdcardsend_cmd(_this,CMD0, 0) == 1) { /* Put the card SPI/Idle state */ + Timer1 = 1000; /* Initialization timeout = 1 sec */ + if (sdcardsend_cmd(_this,CMD8, 0x1AA) == 1) { /* SDv2? */ + ((sdcardDev*)_this->phy)->rcvr_mmc(((sdcardDev*)_this->phy)->phy,ocr, 4); + //for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get 32 bit return value of R7 resp */ + if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* Is the card supports vcc of 2.7-3.6V? */ + while (Timer1 && sdcardsend_cmd(_this,ACMD41, 1UL << 30)) ; /* Wait for end of initialization with ACMD41(HCS) */ + if (Timer1 && sdcardsend_cmd(_this,CMD58, 0) == 0) { /* Check CCS bit in the OCR */ + //for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); + ((sdcardDev*)_this->phy)->rcvr_mmc(((sdcardDev*)_this->phy)->phy,ocr, 4); + ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* Card id SDv2 */ + } + } + } else { /* Not SDv2 card */ + if (sdcardsend_cmd(_this,ACMD41, 0) <= 1) { /* SDv1 or MMC? */ + ty = CT_SD1; cmd = ACMD41; /* SDv1 (ACMD41(0)) */ + } else { + ty = CT_MMC; cmd = CMD1; /* MMCv3 (CMD1(0)) */ + } + while (Timer1 && sdcardsend_cmd(_this,cmd, 0)) ; /* Wait for end of initialization */ + if (!Timer1 || sdcardsend_cmd(_this,CMD16, 512) != 0) /* Set block length: 512 */ + ty = 0; + } + } + ((sdcardDev*)_this->phy)->CardType = ty; /* Card type */ + + if (ty) { /* OK */ + ((sdcardDev*)_this->phy)->Stat &= ~STA_NOINIT; /* Clear STA_NOINIT flag */ + sdcardsend_cmd(_this,CMD58, 0); + ((sdcardDev*)_this->phy)->rcvr_mmc(((sdcardDev*)_this->phy)->phy,ocr, 4); + do + { + speed+=1000000; + ((sdcardDev*)_this->phy)->setspeed(((sdcardDev*)_this->phy)->phy,speed); + sdcardsend_cmd(_this,CMD58, 0); + ((sdcardDev*)_this->phy)->rcvr_mmc(((sdcardDev*)_this->phy)->phy,ocr2, 4); + for(n=0;n<4;n++) + { + if(ocr[n]!=ocr2[n]) + { + n=0; + break; + } + } + if(speed>(50*1000*1000)) + { + break; + } + }while(n); + if(!n) + { + speed-=1000000; + ((sdcardDev*)_this->phy)->setspeed(((sdcardDev*)_this->phy)->phy,speed); + } + + } else { /* Failed */ + //power_off(); + ((sdcardDev*)_this->phy)->Stat = STA_NOINIT; + } + sdcarddeselect (_this); + return ((sdcardDev*)_this->phy)->Stat; +} + + + + + + + + + + +DRESULT sdcarddisk_read (blkdevice* _this,char *buff,unsigned int sector,char count) +{ + DSTATUS s; + + + s = sdcarddisk_status(_this); + if (s & STA_NOINIT) return RES_NOTRDY; + if (!count) return RES_PARERR; + if (!(((sdcardDev*)_this->phy)->CardType & CT_BLOCK)) sector *= 512; /* Convert LBA to byte address if needed */ + + if (count == 1) { /* Single block read */ + if ((sdcardsend_cmd(_this,CMD17, sector) == 0) && sdcardrcvr_datablock((sdcardDev*)(_this->phy),buff, 512)) + count = 0; + } + else { /* Multiple block read */ + if (sdcardsend_cmd(_this,CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */ + do { + if (!sdcardrcvr_datablock (((sdcardDev*)_this->phy),buff, 512)) break; + buff += 512; + } while (--count); + sdcardsend_cmd(_this,CMD12, 0); /* STOP_TRANSMISSION */ + } + } + sdcarddeselect (_this); + + return count ? RES_ERROR : RES_OK; +} + + + + + +DRESULT sdcarddisk_write (blkdevice* _this,const char *buff,unsigned int sector,char count) +{ + DSTATUS s; + + + s = sdcarddisk_status(_this); + if (s & STA_NOINIT) return RES_NOTRDY; + if (s & STA_PROTECT) return RES_WRPRT; + if (!count) return RES_PARERR; + if (!(((sdcardDev*)_this->phy)->CardType & CT_BLOCK)) sector *= 512; /* Convert LBA to byte address if needed */ + + if (count == 1) { /* Single block write */ + if ((sdcardsend_cmd(_this,CMD24, sector) == 0) /* WRITE_BLOCK */ + && sdcardxmit_datablock (((sdcardDev*)_this->phy),buff, 0xFE)) + count = 0; + } + else { /* Multiple block write */ + if (((sdcardDev*)_this->phy)->CardType & CT_SDC) sdcardsend_cmd(_this,ACMD23, count); + if (sdcardsend_cmd(_this,CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */ + do { + if (!sdcardxmit_datablock (((sdcardDev*)_this->phy),buff, 0xFC)) break; + buff += 512; + } while (--count); + if (!sdcardxmit_datablock (((sdcardDev*)_this->phy),0, 0xFD)) /* STOP_TRAN token */ + count = 1; + } + } + sdcarddeselect (_this); + + return count ? RES_ERROR : RES_OK; +} + + +DRESULT sdcarddisk_ioctl (blkdevice* _this,char ctrl,void *buff) +{ + DRESULT res; + const unsigned char dummy=0xff; + char n, csd[16], *ptr = buff; + unsigned short csize; + unsigned long *dp, st, ed; + + + if (_this==0) return RES_PARERR; /* Check parameter */ + if (((sdcardDev*)_this->phy)->Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */ + + res = RES_ERROR; + + switch (ctrl) { + case CTRL_SYNC : /* Wait for end of internal write process of the drive */ + if (sdcardselect (_this)) { + sdcarddeselect (_this); + res = RES_OK; + } + break; + + case GET_SECTOR_COUNT : /* Get drive capacity in unit of sector (DWORD) */ + if ((sdcardsend_cmd(_this,CMD9, 0) == 0) && sdcardrcvr_datablock (((sdcardDev*)_this->phy),csd, 16)) { + if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */ + csize = csd[9] + ((unsigned short)csd[8] << 8) + 1; + *(unsigned long*)buff = (unsigned long)csize << 10; + } else { /* SDC ver 1.XX or MMC ver 3 */ + n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2; + csize = (csd[8] >> 6) + ((unsigned short)csd[7] << 2) + ((unsigned short)(csd[6] & 3) << 10) + 1; + *(unsigned long*)buff = (unsigned long)csize << (n - 9); + } + res = RES_OK; + } + break; + + case GET_SECTOR_SIZE : /* Get sector size in unit of byte (WORD) */ + *(unsigned short*)buff = 512; + res = RES_OK; + break; + + case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */ + if (((sdcardDev*)_this->phy)->CardType & CT_SD2) { /* SDC ver 2.00 */ + if (sdcardsend_cmd(_this,ACMD13, 0) == 0) { /* Read SD status */ + ((sdcardDev*)_this->phy)->xmit_mmc(((sdcardDev*)_this->phy)->phy,&dummy, 1); + if (sdcardrcvr_datablock (((sdcardDev*)_this->phy),csd, 16)) { /* Read partial block */ + for (n = 64 - 16; n; n--) ((sdcardDev*)_this->phy)->xmit_mmc(((sdcardDev*)_this->phy)->phy,&dummy, 1); /* Purge trailing data */ + *(unsigned long*)buff = 16UL << (csd[10] >> 4); + res = RES_OK; + ((sdcardDev*)_this->phy)->xmit_mmc(((sdcardDev*)_this->phy)->phy,&dummy, 1); + } + } + } else { /* SDC ver 1.XX or MMC */ + if ((sdcardsend_cmd(_this,CMD9, 0) == 0) && sdcardrcvr_datablock (((sdcardDev*)_this->phy),csd, 16)) { /* Read CSD */ + if (((sdcardDev*)_this->phy)->CardType & CT_SD1) { /* SDC ver 1.XX */ + *(unsigned long*)buff = (((csd[10] & 63) << 1) + ((unsigned short)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1); + } else { /* MMC */ + *(unsigned long*)buff = ((unsigned short)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1); + } + res = RES_OK; + } + } + break; + + case CTRL_ERASE_SECTOR : /* Erase a block of sectors (used when _USE_ERASE == 1) */ + if (!(((sdcardDev*)_this->phy)->CardType & CT_SDC)) break; /* Check if the card is SDC */ + if (sdcarddisk_ioctl(_this, MMC_GET_CSD, csd)) break; /* Get CSD */ + if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; /* Check if sector erase can be applied to the card */ + dp = buff; st = dp[0]; ed = dp[1]; /* Load sector block */ + if (!(((sdcardDev*)_this->phy)->CardType & CT_BLOCK)) { + st *= 512; ed *= 512; + } + if (sdcardsend_cmd(_this,CMD32, st) == 0 && sdcardsend_cmd(_this,CMD33, ed) == 0 && sdcardsend_cmd(_this,CMD38, 0) == 0 && sdcardwait_ready(((sdcardDev*)_this->phy))) /* Erase sector block */ + res = RES_OK; /* FatFs does not check result of this command */ + break; + + /* Following command are not used by FatFs module */ + + case MMC_GET_TYPE : /* Get MMC/SDC type (BYTE) */ + *ptr = ((sdcardDev*)_this->phy)->CardType; + res = RES_OK; + break; + + case MMC_GET_CSD : /* Read CSD (16 bytes) */ + if (sdcardsend_cmd(_this,CMD9, 0) == 0 /* READ_CSD */ + && sdcardrcvr_datablock (((sdcardDev*)_this->phy),ptr, 16)) + res = RES_OK; + break; + + case MMC_GET_CID : /* Read CID (16 bytes) */ + if (sdcardsend_cmd(_this,CMD10, 0) == 0 /* READ_CID */ + && sdcardrcvr_datablock (((sdcardDev*)_this->phy),ptr, 16)) + res = RES_OK; + break; + + case MMC_GET_OCR : /* Read OCR (4 bytes) */ + if (sdcardsend_cmd(_this,CMD58, 0) == 0) { /* READ_OCR */ + //for (n = 4; n; n--) *ptr++ = + ((sdcardDev*)_this->phy)->rcvr_mmc(((sdcardDev*)_this->phy)->phy,ptr, 4); + res = RES_OK; + } + break; + + case MMC_GET_SDSTAT : /* Read SD status (64 bytes) */ + if (sdcardsend_cmd(_this,ACMD13, 0) == 0) { /* SD_STATUS */ + ((sdcardDev*)_this->phy)->xmit_mmc(((sdcardDev*)_this->phy)->phy,&dummy, 1); + if (sdcardrcvr_datablock (((sdcardDev*)_this->phy),ptr, 64)) + res = RES_OK; + } + break; + + default: + res = RES_PARERR; + } + + sdcarddeselect (_this); + + return res; +} + + + +void sdcardmake(sdcardDev* sdcard,UHANDLE phy,void (*rcvr_mmc) (UHANDLE,char *,unsigned int ),void (*xmit_mmc) (UHANDLE,const char *,unsigned int ),void (*setspeed) (UHANDLE phy,unsigned int speed),unsigned int (*getspeed) (UHANDLE phy)) +{ + sdcard->phy = phy; + sdcard->rcvr_mmc = rcvr_mmc; + sdcard->xmit_mmc = xmit_mmc; + sdcard->setspeed = setspeed; + sdcard->getspeed = getspeed; +} + + void sdcardmakeblkdev(blkdevice* dev,sdcardDev* sdcard, blkdevselect_t select,blkdevpower_t power,blkdevdetect_t detect,blkdevwriteprotected_t writeprotected) + { + dev->phy=sdcard; + dev->select=select; + dev->power = power; + dev->detect = detect; + dev->writeprotected = writeprotected; + dev->write = sdcarddisk_write; + dev->read = sdcarddisk_read; + dev->ioctl = sdcarddisk_ioctl; + dev->initialize = sdcarddisk_initialize; + dev->status = sdcarddisk_status; + + } + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/FILE_SYSTEM/SDCARD/sdcard.h b/lib/src/common/FILE_SYSTEM/SDCARD/sdcard.h new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/SDCARD/sdcard.h @@ -0,0 +1,118 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef SDCARD_H +#define SDCARD_H +#include "blkdevice.h" +#include +#include + +/* MMC/SD command */ +#define CMD0 (0) /* GO_IDLE_STATE */ +#define CMD1 (1) /* SEND_OP_COND (MMC) */ +#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */ +#define CMD8 (8) /* SEND_IF_COND */ +#define CMD9 (9) /* SEND_CSD */ +#define CMD10 (10) /* SEND_CID */ +#define CMD12 (12) /* STOP_TRANSMISSION */ +#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */ +#define CMD16 (16) /* SET_BLOCKLEN */ +#define CMD17 (17) /* READ_SINGLE_BLOCK */ +#define CMD18 (18) /* READ_MULTIPLE_BLOCK */ +#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */ +#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */ +#define CMD24 (24) /* WRITE_BLOCK */ +#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */ +#define CMD32 (32) /* ERASE_ER_BLK_START */ +#define CMD33 (33) /* ERASE_ER_BLK_END */ +#define CMD38 (38) /* ERASE */ +#define CMD55 (55) /* APP_CMD */ +#define CMD58 (58) /* READ_OCR */ + +/* Card type flags (CardType) */ +#define CT_MMC 0x01 /* MMC ver 3 */ +#define CT_SD1 0x02 /* SD ver 1 */ +#define CT_SD2 0x04 /* SD ver 2 */ +#define CT_SDC (CT_SD1|CT_SD2) /* SD */ +#define CT_BLOCK 0x08 /* Block addressing */ + +struct sdcard_str +{ + UHANDLE phy; + void (*rcvr_mmc) (UHANDLE phy,char *buff,unsigned int bc); + void (*xmit_mmc) (UHANDLE phy,const char *buff,unsigned int bc); + void (*setspeed) (UHANDLE phy,unsigned int speed); + unsigned int (*getspeed) (UHANDLE phy); + DSTATUS Stat; + char CardType; +}; + +typedef volatile struct sdcard_str sdcardDev; + +extern void sdcardmake(sdcardDev* sdcard,UHANDLE phy,void (*rcvr_mmc) (UHANDLE,char *,unsigned int ),void (*xmit_mmc) (UHANDLE,const char *,unsigned int ),void (*setspeed) (UHANDLE phy,unsigned int speed),unsigned int (*getspeed) (UHANDLE phy)); +extern void sdcardmakeblkdev(blkdevice* dev,sdcardDev* sdcard, blkdevselect_t select,blkdevpower_t power,blkdevdetect_t detect,blkdevwriteprotected_t writeprotected); + +extern int sdcardselect (blkdevice* _this); +extern void sdcarddeselect (blkdevice* _this); +extern int sdcardwait_ready (sdcardDev* sdcard); +extern int sdcardxmit_datablock (sdcardDev* sdcard,const char *buff,char token); +extern int sdcardrcvr_datablock (sdcardDev* sdcard,char *buff,unsigned int btr); +extern char sdcardsend_cmd (blkdevice* _this,char cmd,unsigned int arg); + +extern DSTATUS sdcarddisk_status (blkdevice* _this); +extern DSTATUS sdcarddisk_initialize (blkdevice* _this); +extern DRESULT sdcarddisk_read (blkdevice* _this,char *buff,unsigned int sector,char count); +extern DRESULT sdcarddisk_write (blkdevice* _this,const char *buff,unsigned int sector,char count); +extern DRESULT sdcarddisk_ioctl (blkdevice* _this,char ctrl,void *buff); + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/FILE_SYSTEM/SDCARD/sdcard.pro b/lib/src/common/FILE_SYSTEM/SDCARD/sdcard.pro new file mode 100644 --- /dev/null +++ b/lib/src/common/FILE_SYSTEM/SDCARD/sdcard.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +lpc17XX.ARCH = lpc17XX-arm-noabi-gcc +lpc17XX.TARGET = libsdcard +lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_SDCARD) +lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_SDCARD) + +lpc17XX.LIBS += SSP BLKDEVICE UCSTRINGS UHANDLE + +lpc17XX.SOURCES += sdcard.c + + +lpc17XX.HEADERS += sdcard.h + + + +lpc21XX.ARCH = lpc21XX-arm-noabi-gcc +lpc21XX.TARGET = libsdcard +lpc21XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_SDCARD) +lpc21XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_SDCARD) + +lpc21XX.LIBS += SSP BLKDEVICE + +lpc21XX.SOURCES += sdcard.c + + +lpc21XX.HEADERS += sdcard.h diff --git a/lib/src/common/HEXVIEWER/Makefile b/lib/src/common/HEXVIEWER/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/common/HEXVIEWER/Makefile @@ -0,0 +1,11 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +all: + make -f lpc17XX.mk + make -f lpc21XX.mk + +clean: + make clean -f lpc17XX.mk + make clean -f lpc21XX.mk diff --git a/lib/src/common/HEXVIEWER/hexviewer.c b/lib/src/common/HEXVIEWER/hexviewer.c new file mode 100644 --- /dev/null +++ b/lib/src/common/HEXVIEWER/hexviewer.c @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------------ +#-- This file is a part of the libuc, microcontroler library +#-- Copyright (C) 2011, Alexis Jeandet +#-- +#-- This program is free software; you can redistribute it and/or modify +#-- it under the terms of the GNU General Public License as published by +#-- the Free Software Foundation; either version 3 of the License, or +#-- (at your option) any later version. +#-- +#-- This program is distributed in the hope that it will be useful, +#-- but WITHOUT ANY WARRANTY; without even the implied warranty of +#-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#-- GNU General Public License for more details. +#-- +#-- You should have received a copy of the GNU General Public License +#-- along with this program; if not, write to the Free Software +#-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#------------------------------------------------------------------------------- +#-- Author : Alexis Jeandet +#-- Mail : alexis.jeandet@gmail.com +#-------------------------------------------------------------------------------*/ +#include "hexviewer.h" + +void hexviewershow(const char* table,unsigned int size,unsigned int offset) +{ + int i=0,n=0; + if(!offset) + libucprintf("00"); + libucprintf(" "); + for(i=0;i<(size);i+=16) + { + libucprintf("%X:\t",n+i+offset); + for(n=0;n<16;n++) + { + if(table[n+i]==0)libucprintf("0"); + if(0x10>table[n+i])libucprintf("0"); + libucprintf("%X ",0xFF & table[n+i]); + if((n & 3)==3)libucprintf(" "); + } + libucprintf("\t "); + for(n=0;n<16;n++) + { + if(33<=table[n+i]) + { + if(126>=table[n+i]) + libucprintf("%c",0x7f & table[n+i]); + else + libucprintf("."); + } + else + libucprintf("."); + } + libucprintf("\n\r "); + if((i & (3<<4))==(3<<4))libucprintf("\n\r "); + } +} + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/HEXVIEWER/hexviewer.h b/lib/src/common/HEXVIEWER/hexviewer.h new file mode 100644 --- /dev/null +++ b/lib/src/common/HEXVIEWER/hexviewer.h @@ -0,0 +1,52 @@ +/*------------------------------------------------------------------------------ +#-- This file is a part of the libuc, microcontroler library +#-- Copyright (C) 2011, Alexis Jeandet +#-- +#-- This program is free software; you can redistribute it and/or modify +#-- it under the terms of the GNU General Public License as published by +#-- the Free Software Foundation; either version 3 of the License, or +#-- (at your option) any later version. +#-- +#-- This program is distributed in the hope that it will be useful, +#-- but WITHOUT ANY WARRANTY; without even the implied warranty of +#-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#-- GNU General Public License for more details. +#-- +#-- You should have received a copy of the GNU General Public License +#-- along with this program; if not, write to the Free Software +#-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#------------------------------------------------------------------------------- +#-- Author : Alexis Jeandet +#-- Mail : alexis.jeandet@gmail.com +#-------------------------------------------------------------------------------*/ +#ifndef HEXVIEWER_H +#define HEXVIEWER_H + +#include + + + + +extern void hexviewershow(const char* table,unsigned int size,unsigned int offset); + + +#endif + + + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/HEXVIEWER/hexviewer.pro b/lib/src/common/HEXVIEWER/hexviewer.pro new file mode 100644 --- /dev/null +++ b/lib/src/common/HEXVIEWER/hexviewer.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +lpc17XX.ARCH = lpc17XX-arm-noabi-gcc +lpc17XX.TARGET = libhexviewer +lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_HEXVIEWER) +lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_HEXVIEWER) + +lpc17XX.LIBS += UCSTRINGS + +lpc17XX.SOURCES += hexviewer.c + + +lpc17XX.HEADERS += hexviewer.h + + + +lpc21XX.ARCH = lpc21XX-arm-noabi-gcc +lpc21XX.TARGET = libhexviewer +lpc21XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_HEXVIEWER) +lpc21XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_HEXVIEWER) + +lpc21XX.LIBS += UCSTRINGS + +lpc21XX.SOURCES += hexviewer.c + + +lpc21XX.HEADERS += hexviewer.h diff --git a/lib/src/common/HEXVIEWER/lpc17XX.mk b/lib/src/common/HEXVIEWER/lpc17XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/HEXVIEWER/lpc17XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_HEXVIEWER) +HEADERS += hexviewer.h +LIBSOURCES += hexviewer.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc17XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc +TARGET=libhexviewer +LIBUC_INCLUDES=$(LIBUC_INC_DIR_UCSTRINGS_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_HEXVIEWER) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_HEXVIEWER) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/HEXVIEWER/lpc21XX.mk b/lib/src/common/HEXVIEWER/lpc21XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/HEXVIEWER/lpc21XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_HEXVIEWER) +HEADERS += hexviewer.h +LIBSOURCES += hexviewer.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libhexviewer +LIBUC_INCLUDES=$(LIBUC_INC_DIR_UCSTRINGS_CMD) $(LIBUC_INC_DIR_UCSTRINGS_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) $(LIBUC_LIBS_DIR_UCSTRINGS_CMD) $(LIBUC_LIBS_UCSTRINGS) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_HEXVIEWER) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_HEXVIEWER) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/Makefile b/lib/src/common/Makefile --- a/lib/src/common/Makefile +++ b/lib/src/common/Makefile @@ -4,18 +4,18 @@ LIBUC = /opt/libuc2 include $(LIBUC)/rules/common/rules.mk all:subdir + make -C STRINGS + make -C HEXVIEWER make -C 24LCXX - make -C STRINGS make -C VS10XX - make -C SDCARD - make -C BLOCKDEVICES + make -C FILE_SYSTEM @echo Code compiled clean: + make clean -C STRINGS + make clean -C HEXVIEWER make clean -C 24LCXX - make clean -C STRINGS make clean -C VS10XX - make clean -C SDCARD - make clean -C BLOCKDEVICES + make clean -C FILE_SYSTEM @echo Code compiled diff --git a/lib/src/common/STRINGS/Makefile b/lib/src/common/STRINGS/Makefile --- a/lib/src/common/STRINGS/Makefile +++ b/lib/src/common/STRINGS/Makefile @@ -5,3 +5,7 @@ LIBUC = /opt/libuc2 all: make -f lpc17XX.mk make -f lpc21XX.mk + +clean: + make clean -f lpc17XX.mk + make clean -f lpc21XX.mk diff --git a/lib/src/common/STRINGS/libucstrings.c b/lib/src/common/STRINGS/libucstrings.c --- a/lib/src/common/STRINGS/libucstrings.c +++ b/lib/src/common/STRINGS/libucstrings.c @@ -1,4 +1,4 @@ -#/*------------------------------------------------------------------------------ +/*------------------------------------------------------------------------------ #-- This file is a part of the libuc, microcontroler library #-- Copyright (C) 2011, Alexis Jeandet #-- @@ -188,11 +188,11 @@ int libucprintf(const char* format,...) switch(*format) { case 'c': - consoleputc((char)va_arg(ap,int)); + consoleputc((char)(0x7f & va_arg(ap,int))); format++; break; case 'd': - _d_prtconv_(va_arg(ap,int)) ; + _d_prtconv_(va_arg(ap,int)); format++; break; case 'e': diff --git a/lib/src/common/STRINGS/libucstrings.h b/lib/src/common/STRINGS/libucstrings.h --- a/lib/src/common/STRINGS/libucstrings.h +++ b/lib/src/common/STRINGS/libucstrings.h @@ -1,4 +1,4 @@ -#/*------------------------------------------------------------------------------ +/*------------------------------------------------------------------------------ #-- This file is a part of the libuc, microcontroler library #-- Copyright (C) 2011, Alexis Jeandet #-- diff --git a/lib/src/common/STRINGS/lpc17XX.mk b/lib/src/common/STRINGS/lpc17XX.mk --- a/lib/src/common/STRINGS/lpc17XX.mk +++ b/lib/src/common/STRINGS/lpc17XX.mk @@ -4,7 +4,10 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_INC_DIR_UCSTRINGS) HEADERS += libucstrings.h LIBSOURCES += libucstrings.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc17XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc TARGET=libucstrings @@ -17,3 +20,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/STRINGS/lpc21XX.mk b/lib/src/common/STRINGS/lpc21XX.mk --- a/lib/src/common/STRINGS/lpc21XX.mk +++ b/lib/src/common/STRINGS/lpc21XX.mk @@ -4,7 +4,10 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_INC_DIR_UCSTRINGS) HEADERS += libucstrings.h LIBSOURCES += libucstrings.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc21XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc TARGET=libucstrings @@ -17,3 +20,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/UHANDLE/Makefile b/lib/src/common/UHANDLE/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/common/UHANDLE/Makefile @@ -0,0 +1,11 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +all: + make -f lpc17XX.mk + make -f lpc21XX.mk + +clean: + make clean -f lpc17XX.mk + make clean -f lpc21XX.mk diff --git a/lib/src/common/UHANDLE/lpc17XX.mk b/lib/src/common/UHANDLE/lpc17XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/UHANDLE/lpc17XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_UHANDLE) +HEADERS += uhandle.h +LIBSOURCES += uhandle.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc17XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc +TARGET=libuhandle +LIBUC_INCLUDES= +LIBUC_LIBRARIES= +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_UHANDLE) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_UHANDLE) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/UHANDLE/lpc21XX.mk b/lib/src/common/UHANDLE/lpc21XX.mk new file mode 100644 --- /dev/null +++ b/lib/src/common/UHANDLE/lpc21XX.mk @@ -0,0 +1,29 @@ +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_UHANDLE) +HEADERS += uhandle.h +LIBSOURCES += uhandle.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libuhandle +LIBUC_INCLUDES= +LIBUC_LIBRARIES= +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_UHANDLE) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_UHANDLE) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/UHANDLE/uhandle.c b/lib/src/common/UHANDLE/uhandle.c new file mode 100644 --- /dev/null +++ b/lib/src/common/UHANDLE/uhandle.c @@ -0,0 +1,21 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ diff --git a/lib/src/common/UHANDLE/uhandle.h b/lib/src/common/UHANDLE/uhandle.h new file mode 100644 --- /dev/null +++ b/lib/src/common/UHANDLE/uhandle.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2012, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef UHANDLE_H +#define UHANDLE_H + +typedef volatile void* UHANDLE; + +#define uhandlevalide(HANDLE) ((HANDLE)!=0) + +#endif diff --git a/lib/src/common/UHANDLE/uhandle.pro b/lib/src/common/UHANDLE/uhandle.pro new file mode 100644 --- /dev/null +++ b/lib/src/common/UHANDLE/uhandle.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +lpc17XX.ARCH = lpc17XX-arm-noabi-gcc +lpc17XX.TARGET = libuhandle +lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_UHANDLE) +lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_UHANDLE) + +lpc17XX.LIBS += + +lpc17XX.SOURCES += uhandle.c + + +lpc17XX.HEADERS += uhandle.h + + + +lpc21XX.ARCH = lpc21XX-arm-noabi-gcc +lpc21XX.TARGET = libuhandle +lpc21XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_UHANDLE) +lpc21XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_UHANDLE) + +lpc21XX.LIBS += + +lpc21XX.SOURCES += uhandle.c + + +lpc21XX.HEADERS += uhandle.h diff --git a/lib/src/common/VS10XX/Makefile b/lib/src/common/VS10XX/Makefile --- a/lib/src/common/VS10XX/Makefile +++ b/lib/src/common/VS10XX/Makefile @@ -5,12 +5,15 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_INC_DIR_VS10XX) HEADERS += vs1053.h LIBSOURCES += vs1053.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc17XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc TARGET=libvs10XX -LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_SSP_CMD) -LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_SSP_CMD) $(LIBUC_LIBS_SSP) +LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_SSP_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_SSP_CMD) $(LIBUC_LIBS_SSP) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_VS10XX) HEADERSINSTALLPATH=$(LIBUC_INC_DIR_VS10XX) BSP=generic @@ -18,3 +21,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/common/VS10XX/vs1053.c b/lib/src/common/VS10XX/vs1053.c --- a/lib/src/common/VS10XX/vs1053.c +++ b/lib/src/common/VS10XX/vs1053.c @@ -23,7 +23,7 @@ #include "vs1053.h" //#include -void vs1053open(vs1053Dev* codec,sspDev* dev){ +void vs1053open(vs1053Dev* codec,sspDev dev){ codec->SSP_device = dev; } diff --git a/lib/src/common/VS10XX/vs1053.h b/lib/src/common/VS10XX/vs1053.h --- a/lib/src/common/VS10XX/vs1053.h +++ b/lib/src/common/VS10XX/vs1053.h @@ -1,4 +1,4 @@ -#/*------------------------------------------------------------------------------ +/*------------------------------------------------------------------------------ #-- This file is a part of the libuc, microcontroler library #-- Copyright (C) 2011, Alexis Jeandet #-- @@ -19,7 +19,9 @@ #-- Author : Alexis Jeandet #-- Mail : alexis.jeandet@gmail.com #-------------------------------------------------------------------------------*/ - +#ifndef VS1053_H +#define VS1053_H +#include #define VSMODE 0 #define VSSTATUS 1 @@ -40,13 +42,13 @@ struct vs1053Regs { - sspDev* SSP_device; + sspDev SSP_device; int a; }; typedef struct vs1053Regs vs1053Dev; -void vs1053open(vs1053Dev* codec,sspDev* dev); +void vs1053open(vs1053Dev* codec,sspDev dev); void vs1053softreset(vs1053Dev* dev); int vs1053cmdread(vs1053Dev* dev,char address); void vs1053cmdwrite(vs1053Dev* dev,char address,int value); @@ -55,4 +57,22 @@ extern void vs10XXclearXCS(); extern void vs10XXsetXCS(); extern int vs10XXDREQ(); +#endif + + + + + + + + + + + + + + + + + diff --git a/lib/src/common/VS10XX/vs1053.pro b/lib/src/common/VS10XX/vs1053.pro --- a/lib/src/common/VS10XX/vs1053.pro +++ b/lib/src/common/VS10XX/vs1053.pro @@ -4,7 +4,7 @@ TARGET = libvs10XX TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_VS10XX) HEADERSINSTALLPATH = $(LIBUC_INC_DIR_VS10XX) -LIBS += CORE SSP +LIBS += CORE SSP UHANDLE SOURCES += vs1053.c diff --git a/lib/src/common/_FAT32_/fat32.c b/lib/src/common/_FAT32_/fat32.c new file mode 100644 --- /dev/null +++ b/lib/src/common/_FAT32_/fat32.c @@ -0,0 +1,4077 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - FAT file system module R0.09 (C)ChaN, 2011 +/-----------------------------------------------------------------------------/ +/ FatFs module is a generic FAT file system module for small embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2011, ChaN, all right reserved. +/ +/ * The FatFs module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-----------------------------------------------------------------------------/ +/ Feb 26,'06 R0.00 Prototype. +/ +/ Apr 29,'06 R0.01 First stable version. +/ +/ Jun 01,'06 R0.02 Added FAT12 support. +/ Removed unbuffered mode. +/ Fixed a problem on small (<32M) partition. +/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM). +/ +/ Sep 22,'06 R0.03 Added f_rename(). +/ Changed option _FS_MINIMUM to _FS_MINIMIZE. +/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast. +/ Fixed f_mkdir() creates incorrect directory on FAT32. +/ +/ Feb 04,'07 R0.04 Supported multiple drive system. +/ Changed some interfaces for multiple drive system. +/ Changed f_mountdrv() to f_mount(). +/ Added f_mkfs(). +/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive. +/ Added a capability of extending file size to f_lseek(). +/ Added minimization level 3. +/ Fixed an endian sensitive code in f_mkfs(). +/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG. +/ Added FSInfo support. +/ Fixed DBCS name can result FR_INVALID_NAME. +/ Fixed short seek (<= csize) collapses the file object. +/ +/ Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs(). +/ Fixed f_mkfs() on FAT32 creates incorrect FSInfo. +/ Fixed f_mkdir() on FAT32 creates incorrect directory. +/ Feb 03,'08 R0.05a Added f_truncate() and f_utime(). +/ Fixed off by one error at FAT sub-type determination. +/ Fixed btr in f_read() can be mistruncated. +/ Fixed cached sector is not flushed when create and close without write. +/ +/ Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets(). +/ Improved performance of f_lseek() on moving to the same or following cluster. +/ +/ Apr 01,'09 R0.07 Merged Tiny-FatFs as a configuration option. (_FS_TINY) +/ Added long file name feature. +/ Added multiple code page feature. +/ Added re-entrancy for multitask operation. +/ Added auto cluster size selection to f_mkfs(). +/ Added rewind option to f_readdir(). +/ Changed result code of critical errors. +/ Renamed string functions to avoid name collision. +/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg. +/ Added multiple sector size feature. +/ Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error. +/ Fixed wrong cache control in f_lseek(). +/ Added relative path feature. +/ Added f_chdir() and f_chdrive(). +/ Added proper case conversion to extended char. +/ Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h. +/ Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. +/ Fixed name matching error on the 13 char boundary. +/ Added a configuration option, _LFN_UNICODE. +/ Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. +/ +/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3) +/ Added file lock feature. (_FS_SHARE) +/ Added fast seek feature. (_USE_FASTSEEK) +/ Changed some types on the API, XCHAR->TCHAR. +/ Changed fname member in the FILINFO structure on Unicode cfg. +/ String functions support UTF-8 encoding files on Unicode cfg. +/ Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2) +/ Added sector erase feature. (_USE_ERASE) +/ Moved file lock semaphore table from fs object to the bss. +/ Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. +/ Fixed f_mkfs() creates wrong FAT32 volume. +/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). +/ f_lseek() reports required table size on creating CLMP. +/ Extended format syntax of f_printf function. +/ Ignores duplicated directory separators in given path names. +/ +/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. +/ Added f_fdisk(). (_MULTI_PARTITION = 2) +/---------------------------------------------------------------------------*/ + +#include "fat.h" /* FatFs configurations and declarations */ +#include "blkdevice.h" /* Declarations of low level disk I/O functions */ + + +/*-------------------------------------------------------------------------- + + Module Private Definitions + +---------------------------------------------------------------------------*/ + +#if _FATFS != 6502 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + + +/* Definitions on sector size */ +#if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096 +#error Wrong sector size. +#endif +#if _MAX_SS != 512 +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#else +#define SS(fs) 512U /* Fixed sector size */ +#endif + + +/* Reentrancy related */ +#if _FS_REENTRANT +#if _USE_LFN == 1 +#error Static LFN work area must not be used in re-entrant configuration. +#endif +#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#else +#define ENTER_FF(fs) +#define LEAVE_FF(fs, res) return res +#endif + +#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } + + +/* File shareing feature */ +#if _FS_SHARE +#if _FS_READONLY +#error _FS_SHARE must be 0 on read-only cfg. +#endif +typedef struct { + FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ + DWORD clu; /* File ID 2, directory */ + WORD idx; /* File ID 3, directory index */ + WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */ +} FILESEM; +#endif + + +/* Misc definitions */ +#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO)) +#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);} + + +/* DBCS code ranges and SBCS extend char conversion table */ + +#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ +#define _DF1S 0x81 /* DBC 1st byte range 1 start */ +#define _DF1E 0x9F /* DBC 1st byte range 1 end */ +#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ +#define _DF2E 0xFC /* DBC 1st byte range 2 end */ +#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ +#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ +#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ +#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ + +#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0x80 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 949 /* Korean */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x41 +#define _DS1E 0x5A +#define _DS2S 0x61 +#define _DS2E 0x7A +#define _DS3S 0x81 +#define _DS3E 0xFE + +#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0xA1 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 437 /* U.S. (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,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} + +#elif _CODE_PAGE == 720 /* Arabic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,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} + +#elif _CODE_PAGE == 737 /* Greek (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,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, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 775 /* Baltic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,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,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,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,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} + +#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 857 /* Turkish (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,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,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ +#define _DF1S 0 +#define _EXCVT {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, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,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} + +#elif _CODE_PAGE == 866 /* Russian (OEM) */ +#define _DF1S 0 +#define _EXCVT {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, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,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, \ + 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {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} + +#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ +#define _DF1S 0 +#define _EXCVT {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,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ + 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, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ + 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, \ + 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} + +#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ +#define _DF1S 0 +#define _EXCVT {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,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ + 0xA0,0x21,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, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1253 /* Greek (Windows) */ +#define _DF1S 0 +#define _EXCVT {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,0xA2,0xB8,0xB9,0xBA, \ + 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} + +#elif _CODE_PAGE == 1254 /* Turkish (Windows) */ +#define _DF1S 0 +#define _EXCVT {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,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,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, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ +#define _DF1S 0 +#define _EXCVT {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,0x21,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} + +#elif _CODE_PAGE == 1256 /* Arabic (Windows) */ +#define _DF1S 0 +#define _EXCVT {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,0x8C,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, \ + 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1257 /* Baltic (Windows) */ +#define _DF1S 0 +#define _EXCVT {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,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ + 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, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {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,0xAC,0x9D,0x9E,0x9F, \ + 0xA0,0x21,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, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} + +#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ +#if _USE_LFN +#error Cannot use LFN feature without valid code page. +#endif +#define _DF1S 0 + +#else +#error Unknown code page + +#endif + + +/* Character code support macros */ +#define IsUpper(c) (((c)>='A')&&((c)<='Z')) +#define IsLower(c) (((c)>='a')&&((c)<='z')) +#define IsDigit(c) (((c)>='0')&&((c)<='9')) + +#if _DF1S /* Code page is DBCS */ + +#ifdef _DF2S /* Two 1st byte areas */ +#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) +#else /* One 1st byte area */ +#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) +#endif + +#ifdef _DS3S /* Three 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) +#else /* Two 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) +#endif + +#else /* Code page is SBCS */ + +#define IsDBCS1(c) 0 +#define IsDBCS2(c) 0 + +#endif /* _DF1S */ + + +/* Name status flags */ +#define NS 11 /* Index of name status byte in fn[] */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ + + +/* FAT sub-type boundaries */ +/* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */ +#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ +#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ + + +/* FatFs refers the members in the FAT structures as byte array instead of +/ structure member because the structure is not binary compatible between +/ different platforms */ + +#define BS_jmpBoot 0 /* Jump instruction (3) */ +#define BS_OEMName 3 /* OEM name (8) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */ +#define BPB_NumFATs 16 /* Number of FAT copies (1) */ +#define BPB_RootEntCnt 17 /* Number of root dir entries for FAT12/16 (2) */ +#define BPB_TotSec16 19 /* Volume size [sector] (2) */ +#define BPB_Media 21 /* Media descriptor (1) */ +#define BPB_FATSz16 22 /* FAT size [sector] (2) */ +#define BPB_SecPerTrk 24 /* Track size [sector] (2) */ +#define BPB_NumHeads 26 /* Number of heads (2) */ +#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */ +#define BPB_TotSec32 32 /* Volume size [sector] (4) */ +#define BS_DrvNum 36 /* Physical drive number (2) */ +#define BS_BootSig 38 /* Extended boot signature (1) */ +#define BS_VolID 39 /* Volume serial number (4) */ +#define BS_VolLab 43 /* Volume label (8) */ +#define BS_FilSysType 54 /* File system type (1) */ +#define BPB_FATSz32 36 /* FAT size [sector] (4) */ +#define BPB_ExtFlags 40 /* Extended flags (2) */ +#define BPB_FSVer 42 /* File system version (2) */ +#define BPB_RootClus 44 /* Root dir first cluster (4) */ +#define BPB_FSInfo 48 /* Offset of FSInfo sector (2) */ +#define BPB_BkBootSec 50 /* Offset of backup boot sectot (2) */ +#define BS_DrvNum32 64 /* Physical drive number (2) */ +#define BS_BootSig32 66 /* Extended boot signature (1) */ +#define BS_VolID32 67 /* Volume serial number (4) */ +#define BS_VolLab32 71 /* Volume label (8) */ +#define BS_FilSysType32 82 /* File system type (1) */ +#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ +#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ +#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ +#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ +#define MBR_Table 446 /* MBR: Partition table offset (2) */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define BS_55AA 510 /* Boot sector signature (2) */ + +#define DIR_Name 0 /* Short file name (11) */ +#define DIR_Attr 11 /* Attribute (1) */ +#define DIR_NTres 12 /* NT flag (1) */ +#define DIR_CrtTime 14 /* Created time (2) */ +#define DIR_CrtDate 16 /* Created date (2) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ +#define DIR_WrtTime 22 /* Modified time (2) */ +#define DIR_WrtDate 24 /* Modified date (2) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */ +#define DIR_FileSize 28 /* File size (4) */ +#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */ +#define LDIR_Attr 11 /* LFN attribute (1) */ +#define LDIR_Type 12 /* LFN type (1) */ +#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */ +#define LDIR_FstClusLO 26 /* Filled by zero (0) */ +#define SZ_DIR 32 /* Size of a directory entry */ +#define LLE 0x40 /* Last long entry flag in LDIR_Ord */ +#define DDE 0xE5 /* Deleted directory enrty mark in DIR_Name[0] */ +#define NDDE 0x05 /* Replacement of a character collides with DDE */ + + +/*------------------------------------------------------------*/ +/* Module private work area */ +/*------------------------------------------------------------*/ +/* Note that uninitialized variables with static duration are +/ zeroed/nulled at start-up. If not, the compiler or start-up +/ routine is out of ANSI-C standard. +*/ + +#if _VOLUMES +static +FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ +#else +#error Number of volumes must not be 0. +#endif + +static +WORD Fsid; /* File system mount ID */ + +#if _FS_RPATH +static +BYTE CurrVol; /* Current drive */ +#endif + +#if _FS_SHARE +static +FILESEM Files[_FS_SHARE]; /* File lock semaphores */ +#endif + +#if _USE_LFN == 0 /* No LFN feature */ +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) (dobj).fn = sfn +#define FREE_BUF() + +#elif _USE_LFN == 1 /* LFN feature with static working buffer */ +static WCHAR LfnBuf[_MAX_LFN+1]; +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } +#define FREE_BUF() + +#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } +#define FREE_BUF() + +#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn +#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ + if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ + (dobj).lfn = lfn; (dobj).fn = sfn; } +#define FREE_BUF() ff_memfree(lfn) + +#else +#error Wrong LFN configuration. +#endif + + + + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* String functions */ +/*-----------------------------------------------------------------------*/ + +/* Copy memory to memory */ +static +void mem_cpy (void* dst, const void* src, UINT cnt) { + BYTE *d = (BYTE*)dst; + const BYTE *s = (const BYTE*)src; + +#if _WORD_ACCESS == 1 + while (cnt >= sizeof(int)) { + *(int*)d = *(int*)s; + d += sizeof(int); s += sizeof(int); + cnt -= sizeof(int); + } +#endif + while (cnt--) + *d++ = *s++; +} + +/* Fill memory */ +static +void mem_set (void* dst, int val, UINT cnt) { + BYTE *d = (BYTE*)dst; + + while (cnt--) + *d++ = (BYTE)val; +} + +/* Compare memory to memory */ +static +int mem_cmp (const void* dst, const void* src, UINT cnt) { + const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; + int r = 0; + + while (cnt-- && (r = *d++ - *s++) == 0) ; + return r; +} + +/* Check if chr is contained in the string */ +static +int chk_chr (const char* str, int chr) { + while (*str && *str != chr) str++; + return *str; +} + + + +/*-----------------------------------------------------------------------*/ +/* Request/Release grant to access the volume */ +/*-----------------------------------------------------------------------*/ +#if _FS_REENTRANT + +static +int lock_fs ( + FATFS *fs /* File system object */ +) +{ + return ff_req_grant(fs->sobj); +} + + +static +void unlock_fs ( + FATFS *fs, /* File system object */ + FRESULT res /* Result code to be returned */ +) +{ + if (res != FR_NOT_ENABLED && + res != FR_INVALID_DRIVE && + res != FR_INVALID_OBJECT && + res != FR_TIMEOUT) { + ff_rel_grant(fs->sobj); + } +} +#endif + + + +/*-----------------------------------------------------------------------*/ +/* File shareing control functions */ +/*-----------------------------------------------------------------------*/ +#if _FS_SHARE + +static +FRESULT chk_lock ( /* Check if the file can be accessed */ + DIR* dj, /* Directory object pointing the file to be checked */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i, be; + + /* Search file semaphore table */ + for (i = be = 0; i < _FS_SHARE; i++) { + if (Files[i].fs) { /* Existing entry */ + if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */ + Files[i].clu == dj->sclust && + Files[i].idx == dj->index) break; + } else { /* Blank entry */ + be++; + } + } + if (i == _FS_SHARE) /* The file is not opened */ + return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ + + /* The file has been opened. Reject any open against writing file and all write mode open */ + return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; +} + + +static +int enq_lock (void) /* Check if an entry is available for a new file */ +{ + UINT i; + + for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; + return (i == _FS_SHARE) ? 0 : 1; +} + + +static +UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */ + DIR* dj, /* Directory object pointing the file to register or increment */ + int acc /* Desired access mode (0:Read, !0:Write) */ +) +{ + UINT i; + + + for (i = 0; i < _FS_SHARE; i++) { /* Find the file */ + if (Files[i].fs == dj->fs && + Files[i].clu == dj->sclust && + Files[i].idx == dj->index) break; + } + + if (i == _FS_SHARE) { /* Not opened. Register it as new. */ + for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; + if (i == _FS_SHARE) return 0; /* No space to register (int err) */ + Files[i].fs = dj->fs; + Files[i].clu = dj->sclust; + Files[i].idx = dj->index; + Files[i].ctr = 0; + } + + if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; +} + + +static +FRESULT dec_lock ( /* Decrement file open counter */ + UINT i /* Semaphore index */ +) +{ + WORD n; + FRESULT res; + + + if (--i < _FS_SHARE) { + n = Files[i].ctr; + if (n == 0x100) n = 0; + if (n) n--; + Files[i].ctr = n; + if (!n) Files[i].fs = 0; + res = FR_OK; + } else { + res = FR_INT_ERR; + } + return res; +} + + +static +void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs +) +{ + UINT i; + + for (i = 0; i < _FS_SHARE; i++) { + if (Files[i].fs == fs) Files[i].fs = 0; + } +} +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Change window offset */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT move_window ( + FATFS *fs, /* File system object */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ +) /* Move to zero only writes back dirty window */ +{ + DWORD wsect; + + + wsect = fs->winsect; + if (wsect != sector) { /* Changed current window */ +#if !_FS_READONLY + if (fs->wflag) { /* Write back dirty window if needed */ + if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) + return FR_DISK_ERR; + fs->wflag = 0; + if (wsect < (fs->fatbase + fs->fsize)) { /* In FAT area */ + BYTE nf; + for (nf = fs->n_fats; nf > 1; nf--) { /* Reflect the change to all FAT copies */ + wsect += fs->fsize; + disk_write(fs->drv, fs->win, wsect, 1); + } + } + } +#endif + if (sector) { + if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) + return FR_DISK_ERR; + fs->winsect = sector; + } + } + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Clean-up cached data */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ + FATFS *fs /* File system object */ +) +{ + FRESULT res; + + + res = move_window(fs, 0); + if (res == FR_OK) { + /* Update FSInfo sector if needed */ + if (fs->fs_type == FS_FAT32 && fs->fsi_flag) { + fs->winsect = 0; + /* Create FSInfo structure */ + mem_set(fs->win, 0, 512); + ST_WORD(fs->win+BS_55AA, 0xAA55); + ST_DWORD(fs->win+FSI_LeadSig, 0x41615252); + ST_DWORD(fs->win+FSI_StrucSig, 0x61417272); + ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust); + ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust); + /* Write it into the FSInfo sector */ + disk_write(fs->drv, fs->win, fs->fsi_sector, 1); + fs->fsi_flag = 0; + } + /* Make sure that no pending write process in the physical drive */ + if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) + res = FR_DISK_ERR; + } + + return res; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Get sector# from cluster# */ +/*-----------------------------------------------------------------------*/ + + +DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to be converted */ +) +{ + clst -= 2; + if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ + return clst * fs->csize + fs->database; +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Read value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + + +DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to get the link information */ +) +{ + UINT wc, bc; + BYTE *p; + + + if (clst < 2 || clst >= fs->n_fatent) /* Chack range */ + return 1; + + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc = fs->win[bc % SS(fs)]; bc++; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc |= fs->win[bc % SS(fs)] << 8; + return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); + + case FS_FAT16 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break; + p = &fs->win[clst * 2 % SS(fs)]; + return LD_WORD(p); + + case FS_FAT32 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break; + p = &fs->win[clst * 4 % SS(fs)]; + return LD_DWORD(p) & 0x0FFFFFFF; + } + + return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Change value of a FAT entry */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY + +FRESULT put_fat ( + FATFS *fs, /* File system object */ + DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ + DWORD val /* New value to mark the cluster */ +) +{ + UINT bc; + BYTE *p; + FRESULT res; + + + if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ + res = FR_INT_ERR; + + } else { + switch (fs->fs_type) { + case FS_FAT12 : + bc = clst; bc += bc / 2; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = &fs->win[bc % SS(fs)]; + *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; + bc++; + fs->wflag = 1; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = &fs->win[bc % SS(fs)]; + *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); + break; + + case FS_FAT16 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); + if (res != FR_OK) break; + p = &fs->win[clst * 2 % SS(fs)]; + ST_WORD(p, (WORD)val); + break; + + case FS_FAT32 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); + if (res != FR_OK) break; + p = &fs->win[clst * 4 % SS(fs)]; + val |= LD_DWORD(p) & 0xF0000000; + ST_DWORD(p, val); + break; + + default : + res = FR_INT_ERR; + } + fs->wflag = 1; + } + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Remove a cluster chain */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT remove_chain ( + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to remove a chain from */ +) +{ + FRESULT res; + DWORD nxt; +#if _USE_ERASE + DWORD scl = clst, ecl = clst, resion[2]; +#endif + + if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ + res = FR_INT_ERR; + + } else { + res = FR_OK; + while (clst < fs->n_fatent) { /* Not a last link? */ + nxt = get_fat(fs, clst); /* Get cluster status */ + if (nxt == 0) break; /* Empty cluster? */ + if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ + if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */ + res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */ + if (res != FR_OK) break; + if (fs->free_clust != 0xFFFFFFFF) { /* Update FSInfo */ + fs->free_clust++; + fs->fsi_flag = 1; + } +#if _USE_ERASE + if (ecl + 1 == nxt) { /* Next cluster is contiguous */ + ecl = nxt; + } else { /* End of contiguous clusters */ + resion[0] = clust2sect(fs, scl); /* Start sector */ + resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ + disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */ + scl = ecl = nxt; + } +#endif + clst = nxt; /* Next cluster */ + } + } + + return res; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Stretch or Create a cluster chain */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ +) +{ + DWORD cs, ncl, scl; + FRESULT res; + + + if (clst == 0) { /* Create a new chain */ + scl = fs->last_clust; /* Get suggested start point */ + if (!scl || scl >= fs->n_fatent) scl = 1; + } + else { /* Stretch the current chain */ + cs = get_fat(fs, clst); /* Check the cluster status */ + if (cs < 2) return 1; /* It is an invalid cluster */ + if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ + scl = clst; + } + + ncl = scl; /* Start cluster */ + for (;;) { + ncl++; /* Next cluster */ + if (ncl >= fs->n_fatent) { /* Wrap around */ + ncl = 2; + if (ncl > scl) return 0; /* No free cluster */ + } + cs = get_fat(fs, ncl); /* Get the cluster status */ + if (cs == 0) break; /* Found a free cluster */ + if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ + return cs; + if (ncl == scl) return 0; /* No free cluster */ + } + + res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */ + if (res == FR_OK && clst != 0) { + res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */ + } + if (res == FR_OK) { + fs->last_clust = ncl; /* Update FSINFO */ + if (fs->free_clust != 0xFFFFFFFF) { + fs->free_clust--; + fs->fsi_flag = 1; + } + } else { + ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; + } + + return ncl; /* Return new cluster number or error code */ +} +#endif /* !_FS_READONLY */ + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Convert offset into cluster with link map table */ +/*-----------------------------------------------------------------------*/ + +#if _USE_FASTSEEK +static +DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ + FIL* fp, /* Pointer to the file object */ + DWORD ofs /* File offset to be converted to cluster# */ +) +{ + DWORD cl, ncl, *tbl; + + + tbl = fp->cltbl + 1; /* Top of CLMT */ + cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */ + for (;;) { + ncl = *tbl++; /* Number of cluters in the fragment */ + if (!ncl) return 0; /* End of table? (error) */ + if (cl < ncl) break; /* In this fragment? */ + cl -= ncl; tbl++; /* Next fragment */ + } + return cl + *tbl; /* Return the cluster number */ +} +#endif /* _USE_FASTSEEK */ + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Set directory index */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_sdi ( + DIR *dj, /* Pointer to directory object */ + WORD idx /* Directory index number */ +) +{ + DWORD clst; + WORD ic; + + + dj->index = idx; + clst = dj->sclust; + if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */ + return FR_INT_ERR; + if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ + clst = dj->fs->dirbase; + + if (clst == 0) { /* Static table (root-dir in FAT12/16) */ + dj->clust = clst; + if (idx >= dj->fs->n_rootdir) /* Index is out of range */ + return FR_INT_ERR; + dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ + } + else { /* Dynamic table (sub-dirs or root-dir in FAT32) */ + ic = SS(dj->fs) / SZ_DIR * dj->fs->csize; /* Entries per cluster */ + while (idx >= ic) { /* Follow cluster chain */ + clst = get_fat(dj->fs, clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */ + return FR_INT_ERR; + idx -= ic; + } + dj->clust = clst; + dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ + } + + dj->dir = dj->fs->win + (idx % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; /* Ptr to the entry in the sector */ + + return FR_OK; /* Seek succeeded */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Move directory index next */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */ + DIR *dj, /* Pointer to directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +) +{ + DWORD clst; + WORD i; + + + stretch = stretch; /* To suppress warning on read-only cfg. */ + i = dj->index + 1; + if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ + return FR_NO_FILE; + + if (!(i % (SS(dj->fs) / SZ_DIR))) { /* Sector changed? */ + dj->sect++; /* Next sector */ + + if (dj->clust == 0) { /* Static table */ + if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */ + return FR_NO_FILE; + } + else { /* Dynamic table */ + if (((i / (SS(dj->fs) / SZ_DIR)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */ + clst = get_fat(dj->fs, dj->clust); /* Get next cluster */ + if (clst <= 1) return FR_INT_ERR; + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; + if (clst >= dj->fs->n_fatent) { /* When it reached end of dynamic table */ +#if !_FS_READONLY + BYTE c; + if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */ + clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */ + if (clst == 0) return FR_DENIED; /* No free cluster */ + if (clst == 1) return FR_INT_ERR; + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; + /* Clean-up stretched table */ + if (move_window(dj->fs, 0)) return FR_DISK_ERR; /* Flush active window */ + mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */ + dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */ + for (c = 0; c < dj->fs->csize; c++) { /* Fill the new cluster with 0 */ + dj->fs->wflag = 1; + if (move_window(dj->fs, 0)) return FR_DISK_ERR; + dj->fs->winsect++; + } + dj->fs->winsect -= c; /* Rewind window address */ +#else + return FR_NO_FILE; /* Report EOT */ +#endif + } + dj->clust = clst; /* Initialize data for new cluster */ + dj->sect = clust2sect(dj->fs, clst); + } + } + } + + dj->index = i; + dj->dir = dj->fs->win + (i % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +static +const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN chars in the directory entry */ + + +static +int cmp_lfn ( /* 1:Matched, 0:Not matched */ + WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ + BYTE *dir /* Pointer to the directory entry containing a part of LFN */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */ + s = 0; wc = 1; + do { + uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ + if (wc) { /* Last char has not been processed */ + wc = ff_wtoupper(uc); /* Convert it to upper case */ + if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */ + return 0; /* Not matched */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } while (++s < 13); /* Repeat until all chars in the entry are checked */ + + if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i]) /* Last segment matched but different length */ + return 0; + + return 1; /* The part of LFN matched */ +} + + + +static +int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ + WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */ + BYTE *dir /* Pointer to the directory entry */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + + s = 0; wc = 1; + do { + uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ + if (wc) { /* Last char has not been processed */ + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i++] = wc = uc; /* Store it */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } while (++s < 13); /* Read all character in the entry */ + + if (dir[LDIR_Ord] & LLE) { /* Put terminator if it is the last LFN part */ + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i] = 0; + } + + return 1; +} + + +#if !_FS_READONLY +static +void fit_lfn ( + const WCHAR *lfnbuf, /* Pointer to the LFN buffer */ + BYTE *dir, /* Pointer to the directory entry */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* SFN sum */ +) +{ + UINT i, s; + WCHAR wc; + + + dir[LDIR_Chksum] = sum; /* Set check sum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + ST_WORD(dir+LDIR_FstClusLO, 0); + + i = (ord - 1) * 13; /* Get offset in the LFN buffer */ + s = wc = 0; + do { + if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective char */ + ST_WORD(dir+LfnOfs[s], wc); /* Put it */ + if (!wc) wc = 0xFFFF; /* Padding chars following last char */ + } while (++s < 13); + if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLE; /* Bottom LFN part is the start of LFN sequence */ + dir[LDIR_Ord] = ord; /* Set the LFN order */ +} + +#endif +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Create numbered name */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +void gen_numname ( + BYTE *dst, /* Pointer to generated SFN */ + const BYTE *src, /* Pointer to source SFN to be modified */ + const WCHAR *lfn, /* Pointer to LFN */ + WORD seq /* Sequence number */ +) +{ + BYTE ns[8], c; + UINT i, j; + + + mem_cpy(dst, src, 11); + + if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */ + do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn); + } + + /* itoa (hexdecimal) */ + i = 7; + do { + c = (seq % 16) + '0'; + if (c > '9') c += 7; + ns[i--] = c; + seq /= 16; + } while (seq); + ns[i] = '~'; + + /* Append the number */ + for (j = 0; j < i && dst[j] != ' '; j++) { + if (IsDBCS1(dst[j])) { + if (j == i - 1) break; + j++; + } + } + do { + dst[j++] = (i < 8) ? ns[i++] : ' '; + } while (j < 8); +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Calculate sum of an SFN */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +static +BYTE sum_sfn ( + const BYTE *dir /* Ptr to directory entry */ +) +{ + BYTE sum = 0; + UINT n = 11; + + do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); + return sum; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Find an object in the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_find ( + DIR *dj /* Pointer to the directory object linked to the file name */ +) +{ + FRESULT res; + BYTE c, *dir; +#if _USE_LFN + BYTE a, ord, sum; +#endif + + res = dir_sdi(dj, 0); /* Rewind directory object */ + if (res != FR_OK) return res; + +#if _USE_LFN + ord = sum = 0xFF; +#endif + do { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + dir = dj->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ +#if _USE_LFN /* LFN configuration */ + a = dir[DIR_Attr] & AM_MASK; + if (c == DDE || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (dj->lfn) { + if (c & LLE) { /* Is it start of LFN sequence? */ + sum = dir[LDIR_Chksum]; + c &= ~LLE; ord = c; /* LFN start order */ + dj->lfn_idx = dj->index; + } + /* Check validity of the LFN entry and compare it with given name */ + ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; + } + } else { /* An SFN entry is found */ + if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */ + ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */ + if (!(dj->fn[NS] & NS_LOSS) && !mem_cmp(dir, dj->fn, 11)) break; /* SFN matched? */ + } + } +#else /* Non LFN configuration */ + if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ + break; +#endif + res = dir_next(dj, 0); /* Next entry */ + } while (res == FR_OK); + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read an object from the directory */ +/*-----------------------------------------------------------------------*/ +#if _FS_MINIMIZE <= 1 +static +FRESULT dir_read ( + DIR *dj /* Pointer to the directory object that pointing the entry to be read */ +) +{ + FRESULT res; + BYTE c, *dir; +#if _USE_LFN + BYTE a, ord = 0xFF, sum = 0xFF; +#endif + + res = FR_NO_FILE; + while (dj->sect) { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + dir = dj->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ +#if _USE_LFN /* LFN configuration */ + a = dir[DIR_Attr] & AM_MASK; + if (c == DDE || (!_FS_RPATH && c == '.') || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (c & LLE) { /* Is it start of LFN sequence? */ + sum = dir[LDIR_Chksum]; + c &= ~LLE; ord = c; + dj->lfn_idx = dj->index; + } + /* Check LFN validity and capture it */ + ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; + } else { /* An SFN entry is found */ + if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */ + dj->lfn_idx = 0xFFFF; /* It has no LFN. */ + break; + } + } +#else /* Non LFN configuration */ + if (c != DDE && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */ + break; +#endif + res = dir_next(dj, 0); /* Next entry */ + if (res != FR_OK) break; + } + + if (res != FR_OK) dj->sect = 0; + + return res; +} +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Register an object to the directory */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ + DIR *dj /* Target directory with object name to be created */ +) +{ + FRESULT res; + BYTE c, *dir; +#if _USE_LFN /* LFN configuration */ + WORD n, ne, is; + BYTE sn[12], *fn, sum; + WCHAR *lfn; + + + fn = dj->fn; lfn = dj->lfn; + mem_cpy(sn, fn, 12); + + if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */ + return FR_INVALID_NAME; + + if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ + fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ + for (n = 1; n < 100; n++) { + gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ + res = dir_find(dj); /* Check if the name collides with existing SFN */ + if (res != FR_OK) break; + } + if (n == 100) return FR_DENIED; /* Abort if too many collisions */ + if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ + fn[NS] = sn[NS]; dj->lfn = lfn; + } + + if (sn[NS] & NS_LFN) { /* When LFN is to be created, reserve an SFN + LFN entries. */ + for (ne = 0; lfn[ne]; ne++) ; + ne = (ne + 25) / 13; + } else { /* Otherwise reserve only an SFN entry. */ + ne = 1; + } + + /* Reserve contiguous entries */ + res = dir_sdi(dj, 0); + if (res != FR_OK) return res; + n = is = 0; + do { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + c = *dj->dir; /* Check the entry status */ + if (c == DDE || c == 0) { /* Is it a blank entry? */ + if (n == 0) is = dj->index; /* First index of the contiguous entry */ + if (++n == ne) break; /* A contiguous entry that required count is found */ + } else { + n = 0; /* Not a blank entry. Restart to search */ + } + res = dir_next(dj, 1); /* Next entry with table stretch */ + } while (res == FR_OK); + + if (res == FR_OK && ne > 1) { /* Initialize LFN entry if needed */ + res = dir_sdi(dj, is); + if (res == FR_OK) { + sum = sum_sfn(dj->fn); /* Sum of the SFN tied to the LFN */ + ne--; + do { /* Store LFN entries in bottom first */ + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum); + dj->fs->wflag = 1; + res = dir_next(dj, 0); /* Next entry */ + } while (res == FR_OK && --ne); + } + } + +#else /* Non LFN configuration */ + res = dir_sdi(dj, 0); + if (res == FR_OK) { + do { /* Find a blank entry for the SFN */ + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + c = *dj->dir; + if (c == DDE || c == 0) break; /* Is it a blank entry? */ + res = dir_next(dj, 1); /* Next entry with table stretch */ + } while (res == FR_OK); + } +#endif + + if (res == FR_OK) { /* Initialize the SFN entry */ + res = move_window(dj->fs, dj->sect); + if (res == FR_OK) { + dir = dj->dir; + mem_set(dir, 0, SZ_DIR); /* Clean the entry */ + mem_cpy(dir, dj->fn, 11); /* Put SFN */ +#if _USE_LFN + dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */ +#endif + dj->fs->wflag = 1; + } + } + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Remove an object from the directory */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY && !_FS_MINIMIZE +static +FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ + DIR *dj /* Directory object pointing the entry to be removed */ +) +{ + FRESULT res; +#if _USE_LFN /* LFN configuration */ + WORD i; + + i = dj->index; /* SFN index */ + res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */ + if (res == FR_OK) { + do { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + *dj->dir = DDE; /* Mark the entry "deleted" */ + dj->fs->wflag = 1; + if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ + res = dir_next(dj, 0); /* Next entry */ + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR; + } + +#else /* Non LFN configuration */ + res = dir_sdi(dj, dj->index); + if (res == FR_OK) { + res = move_window(dj->fs, dj->sect); + if (res == FR_OK) { + *dj->dir = DDE; /* Mark the entry "deleted" */ + dj->fs->wflag = 1; + } + } +#endif + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Pick a segment and create the object name in directory form */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT create_name ( + DIR *dj, /* Pointer to the directory object */ + const TCHAR **path /* Pointer to pointer to the segment in the path string */ +) +{ +#ifdef _EXCVT + static const BYTE excvt[] = _EXCVT; /* Upper conversion table for extended chars */ +#endif + +#if _USE_LFN /* LFN configuration */ + BYTE b, cf; + WCHAR w, *lfn; + UINT i, ni, si, di; + const TCHAR *p; + + /* Create LFN in Unicode */ + for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ + lfn = dj->lfn; + si = di = 0; + for (;;) { + w = p[si++]; /* Get a character */ + if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ + if (di >= _MAX_LFN) /* Reject too long name */ + return FR_INVALID_NAME; +#if !_LFN_UNICODE + w &= 0xFF; + if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + b = (BYTE)p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(b)) + return FR_INVALID_NAME; /* Reject invalid sequence */ + w = (w << 8) + b; /* Create a DBC */ + } + w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ + if (!w) return FR_INVALID_NAME; /* Reject invalid code */ +#endif + if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */ + return FR_INVALID_NAME; + lfn[di++] = w; /* Store the Unicode char */ + } + *path = &p[si]; /* Return pointer to the next segment */ + cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ +#if _FS_RPATH + if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */ + (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) { + lfn[di] = 0; + for (i = 0; i < 11; i++) + dj->fn[i] = (i < di) ? '.' : ' '; + dj->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } +#endif + while (di) { /* Strip trailing spaces and dots */ + w = lfn[di-1]; + if (w != ' ' && w != '.') break; + di--; + } + if (!di) return FR_INVALID_NAME; /* Reject nul string */ + + lfn[di] = 0; /* LFN is created */ + + /* Create SFN in directory form */ + mem_set(dj->fn, ' ', 11); + for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ + if (si) cf |= NS_LOSS | NS_LFN; + while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ + + b = i = 0; ni = 8; + for (;;) { + w = lfn[si++]; /* Get an LFN char */ + if (!w) break; /* Break on end of the LFN */ + if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ + cf |= NS_LOSS | NS_LFN; continue; + } + + if (i >= ni || si == di) { /* Extension or end of SFN */ + if (ni == 11) { /* Long extension */ + cf |= NS_LOSS | NS_LFN; break; + } + if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ + if (si > di) break; /* No extension */ + si = di; i = 8; ni = 11; /* Enter extension section */ + b <<= 2; continue; + } + + if (w >= 0x80) { /* Non ASCII char */ +#ifdef _EXCVT + w = ff_convert(w, 0); /* Unicode -> OEM code */ + if (w) w = excvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ +#else + w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ +#endif + cf |= NS_LFN; /* Force create LFN entry */ + } + + if (_DF1S && w >= 0x100) { /* Double byte char (always false on SBCS cfg) */ + if (i >= ni - 1) { + cf |= NS_LOSS | NS_LFN; i = ni; continue; + } + dj->fn[i++] = (BYTE)(w >> 8); + } else { /* Single byte char */ + if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */ + w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } else { + if (IsUpper(w)) { /* ASCII large capital */ + b |= 2; + } else { + if (IsLower(w)) { /* ASCII small capital */ + b |= 1; w -= 0x20; + } + } + } + } + dj->fn[i++] = (BYTE)w; + } + + if (dj->fn[0] == DDE) dj->fn[0] = NDDE; /* If the first char collides with deleted mark, replace it with 0x05 */ + + if (ni == 8) b <<= 2; + if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ + cf |= NS_LFN; + if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended char, NT flags are created */ + if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ + if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ + } + + dj->fn[NS] = cf; /* SFN is created */ + + return FR_OK; + + +#else /* Non-LFN configuration */ + BYTE b, c, d, *sfn; + UINT ni, si, i; + const char *p; + + /* Create file name in directory form */ + for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ + sfn = dj->fn; + mem_set(sfn, ' ', 11); + si = i = b = 0; ni = 8; +#if _FS_RPATH + if (p[si] == '.') { /* Is this a dot entry? */ + for (;;) { + c = (BYTE)p[si++]; + if (c != '.' || si >= 3) break; + sfn[i++] = c; + } + if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; + *path = &p[si]; /* Return pointer to the next segment */ + sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ + return FR_OK; + } +#endif + for (;;) { + c = (BYTE)p[si++]; + if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ + if (c == '.' || i >= ni) { + if (ni != 8 || c != '.') return FR_INVALID_NAME; + i = 8; ni = 11; + b <<= 2; continue; + } + if (c >= 0x80) { /* Extended char? */ + b |= 3; /* Eliminate NT flag */ +#ifdef _EXCVT + c = excvt[c-0x80]; /* Upper conversion (SBCS) */ +#else +#if !_DF1S /* ASCII only cfg */ + return FR_INVALID_NAME; +#endif +#endif + } + if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + d = (BYTE)p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ + return FR_INVALID_NAME; + sfn[i++] = c; + sfn[i++] = d; + } else { /* Single byte code */ + if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ + return FR_INVALID_NAME; + if (IsUpper(c)) { /* ASCII large capital? */ + b |= 2; + } else { + if (IsLower(c)) { /* ASCII small capital? */ + b |= 1; c -= 0x20; + } + } + sfn[i++] = c; + } + } + *path = &p[si]; /* Return pointer to the next segment */ + c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ + + if (!i) return FR_INVALID_NAME; /* Reject nul string */ + if (sfn[0] == DDE) sfn[0] = NDDE; /* When first char collides with DDE, replace it with 0x05 */ + + if (ni == 8) b <<= 2; + if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ + if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */ + + sfn[NS] = c; /* Store NT flag, File name is created */ + + return FR_OK; +#endif +} + + + + +/*-----------------------------------------------------------------------*/ +/* Get file information from directory entry */ +/*-----------------------------------------------------------------------*/ +#if _FS_MINIMIZE <= 1 +static +void get_fileinfo ( /* No return code */ + DIR *dj, /* Pointer to the directory object */ + FILINFO *fno /* Pointer to the file information to be filled */ +) +{ + UINT i; + BYTE nt, *dir; + TCHAR *p, c; + + + p = fno->fname; + if (dj->sect) { + dir = dj->dir; + nt = dir[DIR_NTres]; /* NT flag */ + for (i = 0; i < 8; i++) { /* Copy name body */ + c = dir[i]; + if (c == ' ') break; + if (c == NDDE) c = (TCHAR)DDE; + if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20; +#if _LFN_UNICODE + if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1])) + c = (c << 8) | dir[++i]; + c = ff_convert(c, 1); + if (!c) c = '?'; +#endif + *p++ = c; + } + if (dir[8] != ' ') { /* Copy name extension */ + *p++ = '.'; + for (i = 8; i < 11; i++) { + c = dir[i]; + if (c == ' ') break; + if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20; +#if _LFN_UNICODE + if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1])) + c = (c << 8) | dir[++i]; + c = ff_convert(c, 1); + if (!c) c = '?'; +#endif + *p++ = c; + } + } + fno->fattrib = dir[DIR_Attr]; /* Attribute */ + fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ + fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ + fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ + } + *p = 0; /* Terminate SFN str by a \0 */ + +#if _USE_LFN + if (fno->lfname && fno->lfsize) { + TCHAR *tp = fno->lfname; + WCHAR w, *lfn; + + i = 0; + if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */ + lfn = dj->lfn; + while ((w = *lfn++) != 0) { /* Get an LFN char */ +#if !_LFN_UNICODE + w = ff_convert(w, 0); /* Unicode -> OEM conversion */ + if (!w) { i = 0; break; } /* Could not convert, no LFN */ + if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ + tp[i++] = (TCHAR)(w >> 8); +#endif + if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overflow, no LFN */ + tp[i++] = (TCHAR)w; + } + } + tp[i] = 0; /* Terminate the LFN str by a \0 */ + } +#endif +} +#endif /* _FS_MINIMIZE <= 1 */ + + + + +/*-----------------------------------------------------------------------*/ +/* Follow a file path */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR *dj, /* Directory object to return last directory and found object */ + const TCHAR *path /* Full-path string to find a file or directory */ +) +{ + FRESULT res; + BYTE *dir, ns; + + +#if _FS_RPATH + if (*path == '/' || *path == '\\') { /* There is a heading separator */ + path++; dj->sclust = 0; /* Strip it and start from the root dir */ + } else { /* No heading separator */ + dj->sclust = dj->fs->cdir; /* Start from the current dir */ + } +#else + if (*path == '/' || *path == '\\') /* Strip heading separator if exist */ + path++; + dj->sclust = 0; /* Start from the root dir */ +#endif + + if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ + res = dir_sdi(dj, 0); + dj->dir = 0; + + } else { /* Follow path */ + for (;;) { + res = create_name(dj, &path); /* Get a segment */ + if (res != FR_OK) break; + res = dir_find(dj); /* Find it */ + ns = *(dj->fn+NS); + if (res != FR_OK) { /* Failed to find the object */ + if (res != FR_NO_FILE) break; /* Abort if any hard error occured */ + /* Object not found */ + if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */ + dj->sclust = 0; dj->dir = 0; /* It is the root dir */ + res = FR_OK; + if (!(ns & NS_LAST)) continue; + } else { /* Could not find the object */ + if (!(ns & NS_LAST)) res = FR_NO_PATH; + } + break; + } + if (ns & NS_LAST) break; /* Last segment match. Function completed. */ + dir = dj->dir; /* There is next segment. Follow the sub directory */ + if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ + res = FR_NO_PATH; break; + } + dj->sclust = LD_CLUST(dir); + } + } + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an FAT Volume Boot Record */ +/*-----------------------------------------------------------------------*/ + +static +BYTE check_fs ( /* 0:FAT-VBR, 1:Valid BR but not FAT, 2:Not a BR, 3:Disk error */ + FATFS *fs, /* File system object */ + DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ +) +{ + if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) /* Load boot record */ + return 3; + if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ + return 2; + + if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ + return 0; + if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) + return 0; + + return 1; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file system object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ + const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ + FATFS **rfs, /* Pointer to pointer to the found file system object */ + BYTE chk_wp /* !=0: Check media write protection for write access */ +) +{ + BYTE fmt, b, pi, *tbl; + UINT vol; + DSTATUS stat; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat; + WORD nrsv; + const TCHAR *p = *path; + FATFS *fs; + + /* Get logical drive number from the path name */ + vol = p[0] - '0'; /* Is there a drive number? */ + if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ + p += 2; *path = p; /* Return pointer to the path name */ + } else { /* No drive number is given */ +#if _FS_RPATH + vol = CurrVol; /* Use current drive */ +#else + vol = 0; /* Use drive 0 */ +#endif + } + + /* Check if the file system object is valid or not */ + if (vol >= _VOLUMES) /* Is the drive number valid? */ + return FR_INVALID_DRIVE; + *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ + if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ + + ENTER_FF(fs); /* Lock file system */ + + if (fs->fs_type) { /* If the logical drive has been mounted */ + stat = disk_status(fs->drv); + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ + if (!_FS_READONLY && chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */ + return FR_WRITE_PROTECTED; + return FR_OK; /* The file system object is valid */ + } + } + + /* The file system object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ + + fs->fs_type = 0; /* Clear the file system object */ + fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */ + if (stat & STA_NOINIT) /* Check if the initialization succeeded */ + return FR_NOT_READY; /* Failed to initialize due to no media or hard error */ + if (!_FS_READONLY && chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */ + return FR_WRITE_PROTECTED; +#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ + if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) + return FR_DISK_ERR; +#endif + /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */ + fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */ + if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */ + if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */ + /* Check the partition listed in the partition table */ + pi = LD2PT(vol); + if (pi) pi--; + tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */ + if (tbl[4]) { /* Is the partition existing? */ + bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ + fmt = check_fs(fs, bsect); /* Check the partition */ + } + } + if (fmt == 3) return FR_DISK_ERR; + if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + + /* An FAT volume is found. Following code initializes the file system object */ + + if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ + return FR_NO_FILESYSTEM; + + fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */ + if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32); + fs->fsize = fasize; + + fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */ + if (b != 1 && b != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + fasize *= b; /* Number of sectors for FAT area */ + + fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ + if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + + fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */ + if (fs->n_rootdir % (SS(fs) / SZ_DIR)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ + + tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */ + if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32); + + nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIR); /* RSV+FAT+DIR */ + if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ + if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + fmt = FS_FAT12; + if (nclst >= MIN_FAT16) fmt = FS_FAT16; + if (nclst >= MIN_FAT32) fmt = FS_FAT32; + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->database = bsect + sysect; /* Data start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + if (fmt == FS_FAT32) { + if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Required FAT size) */ + } else { + if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); + } + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than required) */ + return FR_NO_FILESYSTEM; + +#if !_FS_READONLY + /* Initialize cluster allocation information */ + fs->free_clust = 0xFFFFFFFF; + fs->last_clust = 0; + + /* Get fsinfo if available */ + if (fmt == FS_FAT32) { + fs->fsi_flag = 0; + fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo); + if (disk_read(fs->drv, fs->win, fs->fsi_sector, 1) == RES_OK && + LD_WORD(fs->win+BS_55AA) == 0xAA55 && + LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 && + LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) { + fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free); + fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count); + } + } +#endif + fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* File system mount ID */ + fs->winsect = 0; /* Invalidate sector cache */ + fs->wflag = 0; +#if _FS_RPATH + fs->cdir = 0; /* Current directory (root dir) */ +#endif +#if _FS_SHARE /* Clear file lock semaphores */ + clear_lock(fs); +#endif + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file/dir object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ + FATFS *fs, /* Pointer to the file system object */ + WORD id /* Member id of the target object to be checked */ +) +{ + if (!fs || !fs->fs_type || fs->id != id) + return FR_INVALID_OBJECT; + + ENTER_FF(fs); /* Lock file system */ + + if (disk_status(fs->drv) & STA_NOINIT) + return FR_NOT_READY; + + return FR_OK; +} + + + + +/*-------------------------------------------------------------------------- + + Public Functions + +--------------------------------------------------------------------------*/ + + + +/*-----------------------------------------------------------------------*/ +/* Mount/Unmount a Logical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mount ( + BYTE vol, /* Logical drive number to be mounted/unmounted */ + FATFS *fs /* Pointer to new file system object (NULL for unmount)*/ +) +{ + FATFS *rfs; + + + if (vol >= _VOLUMES) /* Check if the drive number is valid */ + return FR_INVALID_DRIVE; + rfs = FatFs[vol]; /* Get current fs object */ + + if (rfs) { +#if _FS_SHARE + clear_lock(rfs); +#endif +#if _FS_REENTRANT /* Discard sync object of the current volume */ + if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; +#endif + rfs->fs_type = 0; /* Clear old fs object */ + } + + if (fs) { + fs->fs_type = 0; /* Clear new fs object */ +#if _FS_REENTRANT /* Create sync object for the new volume */ + if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR; +#endif + } + FatFs[vol] = fs; /* Register new fs object */ + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Open or Create a File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_open ( + FIL *fp, /* Pointer to the blank file object */ + const TCHAR *path, /* Pointer to the file name */ + BYTE mode /* Access mode and file open mode flags */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + fp->fs = 0; /* Clear file object */ + +#if !_FS_READONLY + mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; + res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ)); +#else + mode &= FA_READ; + res = chk_mounted(&path, &dj.fs, 0); +#endif + INIT_BUF(dj); + if (res == FR_OK) + res = follow_path(&dj, path); /* Follow the file path */ + dir = dj.dir; + +#if !_FS_READONLY /* R/W configuration */ + if (res == FR_OK) { + if (!dir) /* Current dir itself */ + res = FR_INVALID_NAME; +#if _FS_SHARE + else + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); +#endif + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { + DWORD dw, cl; + + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ +#if _FS_SHARE + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#else + res = dir_register(&dj); +#endif + mode |= FA_CREATE_ALWAYS; /* File is created */ + dir = dj.dir; /* New entry */ + } + else { /* Any object is already existing */ + if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ + res = FR_DENIED; + } else { + if (mode & FA_CREATE_NEW) /* Cannot create as new file */ + res = FR_EXIST; + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ + dw = get_fattime(); /* Created time */ + ST_DWORD(dir+DIR_CrtTime, dw); + dir[DIR_Attr] = 0; /* Reset attribute */ + ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ + cl = LD_CLUST(dir); /* Get start cluster */ + ST_CLUST(dir, 0); /* cluster = 0 */ + dj.fs->wflag = 1; + if (cl) { /* Remove the cluster chain if exist */ + dw = dj.fs->winsect; + res = remove_chain(dj.fs, cl); + if (res == FR_OK) { + dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ + res = move_window(dj.fs, dw); + } + } + } + } + else { /* Open an existing file */ + if (res == FR_OK) { /* Follow succeeded */ + if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ + res = FR_DENIED; + } + } + } + if (res == FR_OK) { + if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ + mode |= FA__WRITTEN; + fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dir; +#if _FS_SHARE + fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + if (!fp->lockid) res = FR_INT_ERR; +#endif + } + +#else /* R/O configuration */ + if (res == FR_OK) { /* Follow succeeded */ + if (!dir) { /* Current dir itself */ + res = FR_INVALID_NAME; + } else { + if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ + res = FR_NO_FILE; + } + } +#endif + FREE_BUF(); + + if (res == FR_OK) { + fp->flag = mode; /* File access mode */ + fp->sclust = LD_CLUST(dir); /* File start cluster */ + fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ + fp->fptr = 0; /* File pointer */ + fp->dsect = 0; +#if _USE_FASTSEEK + fp->cltbl = 0; /* Normal seek mode */ +#endif + fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_read ( + FIL *fp, /* Pointer to the file object */ + void *buff, /* Pointer to data buffer */ + UINT btr, /* Number of bytes to read */ + UINT *br /* Pointer to number of bytes read */ +) +{ + FRESULT res; + DWORD clst, sect, remain; + UINT rcnt, cc; + BYTE csect, *rbuff = buff; + + + *br = 0; /* Initialize byte counter */ + + res = validate(fp->fs, fp->id); /* Check validity */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Aborted file? */ + LEAVE_FF(fp->fs, FR_INT_ERR); + if (!(fp->flag & FA_READ)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + remain = fp->fsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr; /* Repeat until all data read */ + rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if (!csect) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->sclust; /* Follow from the origin */ + } else { /* Middle or end of the file */ +#if _USE_FASTSEEK + if (fp->cltbl) + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else +#endif + clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */ + } + if (clst < 2) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) { /* Read maximum contiguous sectors directly */ + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - csect; + if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); +#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ +#if _FS_TINY + if (fp->fs->wflag && fp->fs->winsect - sect < cc) + mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); +#else + if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) + mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); +#endif +#endif + rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + continue; + } +#if !_FS_TINY + if (fp->dsect != sect) { /* Load data sector if not in cache */ +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */ + ABORT(fp->fs, FR_DISK_ERR); + } +#endif + fp->dsect = sect; + } + rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ + if (rcnt > btr) rcnt = btr; +#if _FS_TINY + if (move_window(fp->fs, fp->dsect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ +#else + mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ +#endif + } + + LEAVE_FF(fp->fs, FR_OK); +} + + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Write File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_write ( + FIL *fp, /* Pointer to the file object */ + const void *buff, /* Pointer to the data to be written */ + UINT btw, /* Number of bytes to write */ + UINT *bw /* Pointer to number of bytes written */ +) +{ + FRESULT res; + DWORD clst, sect; + UINT wcnt, cc; + const BYTE *wbuff = buff; + BYTE csect; + + + *bw = 0; /* Initialize byte counter */ + + res = validate(fp->fs, fp->id); /* Check validity */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Aborted file? */ + LEAVE_FF(fp->fs, FR_INT_ERR); + if (!(fp->flag & FA_WRITE)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + if ((DWORD)(fp->fsize + btw) < fp->fsize) btw = 0; /* File size cannot reach 4GB */ + + for ( ; btw; /* Repeat until all data written */ + wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if (!csect) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->sclust; /* Follow from the origin */ + if (clst == 0) /* When no cluster is allocated, */ + fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ + } else { /* Middle or end of the file */ +#if _USE_FASTSEEK + if (fp->cltbl) + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else +#endif + clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */ + } + if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ + if (clst == 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } +#if _FS_TINY + if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) /* Write-back sector cache */ + ABORT(fp->fs, FR_DISK_ERR); +#else + if (fp->flag & FA__DIRTY) { /* Write-back sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) { /* Write maximum contiguous sectors directly */ + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - csect; + if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); +#if _FS_TINY + if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); + fp->fs->wflag = 0; + } +#else + if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); + fp->flag &= ~FA__DIRTY; + } +#endif + wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + continue; + } +#if _FS_TINY + if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */ + if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR); + fp->fs->winsect = sect; + } +#else + if (fp->dsect != sect) { /* Fill sector cache with file data */ + if (fp->fptr < fp->fsize && + disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + } +#endif + fp->dsect = sect; + } + wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ + if (wcnt > btw) wcnt = btw; +#if _FS_TINY + if (move_window(fp->fs, fp->dsect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ + fp->fs->wflag = 1; +#else + mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ + fp->flag |= FA__DIRTY; +#endif + } + + if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */ + fp->flag |= FA__WRITTEN; /* Set file change flag */ + + LEAVE_FF(fp->fs, FR_OK); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize the File Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_sync ( + FIL *fp /* Pointer to the file object */ +) +{ + FRESULT res; + DWORD tim; + BYTE *dir; + + + res = validate(fp->fs, fp->id); /* Check validity of the object */ + if (res == FR_OK) { + if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ +#if !_FS_TINY /* Write-back dirty buffer */ + if (fp->flag & FA__DIRTY) { + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + LEAVE_FF(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + /* Update the directory entry */ + res = move_window(fp->fs, fp->dir_sect); + if (res == FR_OK) { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ + ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ + ST_CLUST(dir, fp->sclust); /* Update start cluster */ + tim = get_fattime(); /* Update updated time */ + ST_DWORD(dir+DIR_WrtTime, tim); + fp->flag &= ~FA__WRITTEN; + fp->fs->wflag = 1; + res = sync(fp->fs); + } + } + } + + LEAVE_FF(fp->fs, res); +} + +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Close File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_close ( + FIL *fp /* Pointer to the file object to be closed */ +) +{ + FRESULT res; + +#if _FS_READONLY + FATFS *fs = fp->fs; + res = validate(fs, fp->id); + if (res == FR_OK) fp->fs = 0; /* Discard file object */ + LEAVE_FF(fs, res); + +#else + res = f_sync(fp); /* Flush cached data */ +#if _FS_SHARE + if (res == FR_OK) { /* Decrement open counter */ +#if _FS_REENTRANT + res = validate(fp->fs, fp->id); + if (res == FR_OK) { + res = dec_lock(fp->lockid); + unlock_fs(fp->fs, FR_OK); + } +#else + res = dec_lock(fp->lockid); +#endif + } +#endif + if (res == FR_OK) fp->fs = 0; /* Discard file object */ + return res; +#endif +} + + + + +/*-----------------------------------------------------------------------*/ +/* Current Drive/Directory Handlings */ +/*-----------------------------------------------------------------------*/ + +#if _FS_RPATH >= 1 + +FRESULT f_chdrive ( + BYTE drv /* Drive number */ +) +{ + if (drv >= _VOLUMES) return FR_INVALID_DRIVE; + + CurrVol = drv; + + return FR_OK; +} + + + +FRESULT f_chdir ( + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 0); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the path */ + FREE_BUF(); + if (res == FR_OK) { /* Follow completed */ + if (!dj.dir) { + dj.fs->cdir = dj.sclust; /* Start directory itself */ + } else { + if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ + dj.fs->cdir = LD_CLUST(dj.dir); + else + res = FR_NO_PATH; /* Reached but a file */ + } + } + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + + LEAVE_FF(dj.fs, res); +} + + +#if _FS_RPATH >= 2 +FRESULT f_getcwd ( + TCHAR *path, /* Pointer to the directory path */ + UINT sz_path /* Size of path */ +) +{ + FRESULT res; + DIR dj; + UINT i, n; + DWORD ccl; + TCHAR *tp; + FILINFO fno; + DEF_NAMEBUF; + + + *path = 0; + res = chk_mounted((const TCHAR**)&path, &dj.fs, 0); /* Get current volume */ + if (res == FR_OK) { + INIT_BUF(dj); + i = sz_path; /* Bottom of buffer (dir stack base) */ + dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */ + while ((ccl = dj.sclust) != 0) { /* Repeat while current dir is a sub-dir */ + res = dir_sdi(&dj, 1); /* Get parent dir */ + if (res != FR_OK) break; + res = dir_read(&dj); + if (res != FR_OK) break; + dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */ + res = dir_sdi(&dj, 0); + if (res != FR_OK) break; + do { /* Find the entry links to the child dir */ + res = dir_read(&dj); + if (res != FR_OK) break; + if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ + if (res != FR_OK) break; +#if _USE_LFN + fno.lfname = path; + fno.lfsize = i; +#endif + get_fileinfo(&dj, &fno); /* Get the dir name and push it to the buffer */ + tp = fno.fname; + if (_USE_LFN && *path) tp = path; + for (n = 0; tp[n]; n++) ; + if (i < n + 3) { + res = FR_NOT_ENOUGH_CORE; break; + } + while (n) path[--i] = tp[--n]; + path[--i] = '/'; + } + tp = path; + if (res == FR_OK) { + *tp++ = '0' + CurrVol; /* Put drive number */ + *tp++ = ':'; + if (i == sz_path) { /* Root-dir */ + *tp++ = '/'; + } else { /* Sub-dir */ + do /* Add stacked path str */ + *tp++ = path[i++]; + while (i < sz_path); + } + } + *tp = 0; + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} +#endif /* _FS_RPATH >= 2 */ +#endif /* _FS_RPATH >= 1 */ + + + +#if _FS_MINIMIZE <= 2 +/*-----------------------------------------------------------------------*/ +/* Seek File R/W Pointer */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_lseek ( + FIL *fp, /* Pointer to the file object */ + DWORD ofs /* File pointer from top of file */ +) +{ + FRESULT res; + + + res = validate(fp->fs, fp->id); /* Check validity of the object */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Check abort flag */ + LEAVE_FF(fp->fs, FR_INT_ERR); + +#if _USE_FASTSEEK + if (fp->cltbl) { /* Fast seek */ + DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; + + if (ofs == CREATE_LINKMAP) { /* Create CLMT */ + tbl = fp->cltbl; + tlen = *tbl++; ulen = 2; /* Given table size and required table size */ + cl = fp->sclust; /* Top of the chain */ + if (cl) { + do { + /* Get a fragment */ + tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ + do { + pcl = cl; ncl++; + cl = get_fat(fp->fs, cl); + if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); + if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + } while (cl == pcl + 1); + if (ulen <= tlen) { /* Store the length and top of the fragment */ + *tbl++ = ncl; *tbl++ = tcl; + } + } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */ + } + *fp->cltbl = ulen; /* Number of items used */ + if (ulen <= tlen) + *tbl = 0; /* Terminate table */ + else + res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ + + } else { /* Fast seek */ + if (ofs > fp->fsize) /* Clip offset at the file size */ + ofs = fp->fsize; + fp->fptr = ofs; /* Set file pointer */ + if (ofs) { + fp->clust = clmt_clust(fp, ofs - 1); + dsc = clust2sect(fp->fs, fp->clust); + if (!dsc) ABORT(fp->fs, FR_INT_ERR); + dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1); + if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */ +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */ + ABORT(fp->fs, FR_DISK_ERR); +#endif + fp->dsect = dsc; + } + } + } + } else +#endif + + /* Normal Seek */ + { + DWORD clst, bcs, nsect, ifptr; + + if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ +#if !_FS_READONLY + && !(fp->flag & FA_WRITE) +#endif + ) ofs = fp->fsize; + + ifptr = fp->fptr; + fp->fptr = nsect = 0; + if (ofs) { + bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ + if (ifptr > 0 && + (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ + fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->clust; + } else { /* When seek to back cluster, */ + clst = fp->sclust; /* start from the first cluster */ +#if !_FS_READONLY + if (clst == 0) { /* If no cluster chain, create a new chain */ + clst = create_chain(fp->fs, 0); + if (clst == 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->sclust = clst; + } +#endif + fp->clust = clst; + } + if (clst != 0) { + while (ofs > bcs) { /* Cluster following loop */ +#if !_FS_READONLY + if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ + clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */ + if (clst == 0) { /* When disk gets full, clip file size */ + ofs = bcs; break; + } + } else +#endif + clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); + fp->clust = clst; + fp->fptr += bcs; + ofs -= bcs; + } + fp->fptr += ofs; + if (ofs % SS(fp->fs)) { + nsect = clust2sect(fp->fs, clst); /* Current sector */ + if (!nsect) ABORT(fp->fs, FR_INT_ERR); + nsect += ofs / SS(fp->fs); + } + } + } + if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */ +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */ + ABORT(fp->fs, FR_DISK_ERR); +#endif + fp->dsect = nsect; + } +#if !_FS_READONLY + if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */ + fp->fsize = fp->fptr; + fp->flag |= FA__WRITTEN; + } +#endif + } + + LEAVE_FF(fp->fs, res); +} + + + +#if _FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Create a Directroy Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_opendir ( + DIR *dj, /* Pointer to directory object to create */ + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj->fs, 0); + if (res == FR_OK) { + INIT_BUF(*dj); + res = follow_path(dj, path); /* Follow the path to the directory */ + FREE_BUF(); + if (res == FR_OK) { /* Follow completed */ + if (dj->dir) { /* It is not the root dir */ + if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ + dj->sclust = LD_CLUST(dj->dir); + } else { /* The object is not a directory */ + res = FR_NO_PATH; + } + } + if (res == FR_OK) { + dj->id = dj->fs->id; + res = dir_sdi(dj, 0); /* Rewind dir */ + } + } + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + + LEAVE_FF(dj->fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read Directory Entry in Sequense */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_readdir ( + DIR *dj, /* Pointer to the open directory object */ + FILINFO *fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DEF_NAMEBUF; + + + res = validate(dj->fs, dj->id); /* Check validity of the object */ + if (res == FR_OK) { + if (!fno) { + res = dir_sdi(dj, 0); /* Rewind the directory object */ + } else { + INIT_BUF(*dj); + res = dir_read(dj); /* Read an directory item */ + if (res == FR_NO_FILE) { /* Reached end of dir */ + dj->sect = 0; + res = FR_OK; + } + if (res == FR_OK) { /* A valid entry is found */ + get_fileinfo(dj, fno); /* Get the object information */ + res = dir_next(dj, 0); /* Increment index for next */ + if (res == FR_NO_FILE) { + dj->sect = 0; + res = FR_OK; + } + } + FREE_BUF(); + } + } + + LEAVE_FF(dj->fs, res); +} + + + +#if _FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Get File Status */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_stat ( + const TCHAR *path, /* Pointer to the file path */ + FILINFO *fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DIR dj; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 0); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.dir) /* Found an object */ + get_fileinfo(&dj, fno); + else /* It is root dir */ + res = FR_INVALID_NAME; + } + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Get Number of Free Clusters */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getfree ( + const TCHAR *path, /* Pointer to the logical drive number (root dir) */ + DWORD *nclst, /* Pointer to the variable to return number of free clusters */ + FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */ +) +{ + FRESULT res; + DWORD n, clst, sect, stat; + UINT i; + BYTE fat, *p; + + + /* Get drive number */ + res = chk_mounted(&path, fatfs, 0); + if (res == FR_OK) { + /* If free_clust is valid, return it without full cluster scan */ + if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) { + *nclst = (*fatfs)->free_clust; + } else { + /* Get number of free clusters */ + fat = (*fatfs)->fs_type; + n = 0; + if (fat == FS_FAT12) { + clst = 2; + do { + stat = get_fat(*fatfs, clst); + if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (stat == 1) { res = FR_INT_ERR; break; } + if (stat == 0) n++; + } while (++clst < (*fatfs)->n_fatent); + } else { + clst = (*fatfs)->n_fatent; + sect = (*fatfs)->fatbase; + i = 0; p = 0; + do { + if (!i) { + res = move_window(*fatfs, sect++); + if (res != FR_OK) break; + p = (*fatfs)->win; + i = SS(*fatfs); + } + if (fat == FS_FAT16) { + if (LD_WORD(p) == 0) n++; + p += 2; i -= 2; + } else { + if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; + p += 4; i -= 4; + } + } while (--clst); + } + (*fatfs)->free_clust = n; + if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1; + *nclst = n; + } + } + LEAVE_FF(*fatfs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Truncate File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_truncate ( + FIL *fp /* Pointer to the file object */ +) +{ + FRESULT res; + DWORD ncl; + + + res = validate(fp->fs, fp->id); /* Check validity of the object */ + if (res == FR_OK) { + if (fp->flag & FA__ERROR) { /* Check abort flag */ + res = FR_INT_ERR; + } else { + if (!(fp->flag & FA_WRITE)) /* Check access mode */ + res = FR_DENIED; + } + } + if (res == FR_OK) { + if (fp->fsize > fp->fptr) { + fp->fsize = fp->fptr; /* Set file size to current R/W point */ + fp->flag |= FA__WRITTEN; + if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ + res = remove_chain(fp->fs, fp->sclust); + fp->sclust = 0; + } else { /* When truncate a part of the file, remove remaining clusters */ + ncl = get_fat(fp->fs, fp->clust); + res = FR_OK; + if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (ncl == 1) res = FR_INT_ERR; + if (res == FR_OK && ncl < fp->fs->n_fatent) { + res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF); + if (res == FR_OK) res = remove_chain(fp->fs, ncl); + } + } + } + if (res != FR_OK) fp->flag |= FA__ERROR; + } + + LEAVE_FF(fp->fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Delete a File or Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_unlink ( + const TCHAR *path /* Pointer to the file or directory path */ +) +{ + FRESULT res; + DIR dj, sdj; + BYTE *dir; + DWORD dclst; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; /* Cannot remove dot entry */ +#if _FS_SHARE + if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ +#endif + if (res == FR_OK) { /* The object is accessible */ + dir = dj.dir; + if (!dir) { + res = FR_INVALID_NAME; /* Cannot remove the start directory */ + } else { + if (dir[DIR_Attr] & AM_RDO) + res = FR_DENIED; /* Cannot remove R/O object */ + } + dclst = LD_CLUST(dir); + if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ + if (dclst < 2) { + res = FR_INT_ERR; + } else { + mem_cpy(&sdj, &dj, sizeof(DIR)); /* Check if the sub-dir is empty or not */ + sdj.sclust = dclst; + res = dir_sdi(&sdj, 2); /* Exclude dot entries */ + if (res == FR_OK) { + res = dir_read(&sdj); + if (res == FR_OK /* Not empty dir */ +#if _FS_RPATH + || dclst == sdj.fs->cdir /* Current dir */ +#endif + ) res = FR_DENIED; + if (res == FR_NO_FILE) res = FR_OK; /* Empty */ + } + } + } + if (res == FR_OK) { + res = dir_remove(&dj); /* Remove the directory entry */ + if (res == FR_OK) { + if (dclst) /* Remove the cluster chain if exist */ + res = remove_chain(dj.fs, dclst); + if (res == FR_OK) res = sync(dj.fs); + } + } + } + FREE_BUF(); + } + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create a Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkdir ( + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir, n; + DWORD dsc, dcl, pcl, tim = get_fattime(); + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ + if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_NO_FILE) { /* Can create a new directory */ + dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */ + res = FR_OK; + if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ + if (dcl == 1) res = FR_INT_ERR; + if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) /* Flush FAT */ + res = move_window(dj.fs, 0); + if (res == FR_OK) { /* Initialize the new directory table */ + dsc = clust2sect(dj.fs, dcl); + dir = dj.fs->win; + mem_set(dir, 0, SS(dj.fs)); + mem_set(dir+DIR_Name, ' ', 8+3); /* Create "." entry */ + dir[DIR_Name] = '.'; + dir[DIR_Attr] = AM_DIR; + ST_DWORD(dir+DIR_WrtTime, tim); + ST_CLUST(dir, dcl); + mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */ + dir[33] = '.'; pcl = dj.sclust; + if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) + pcl = 0; + ST_CLUST(dir+SZ_DIR, pcl); + for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ + dj.fs->winsect = dsc++; + dj.fs->wflag = 1; + res = move_window(dj.fs, 0); + if (res != FR_OK) break; + mem_set(dir, 0, SS(dj.fs)); + } + } + if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ + if (res != FR_OK) { + remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ + } else { + dir = dj.dir; + dir[DIR_Attr] = AM_DIR; /* Attribute */ + ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */ + ST_CLUST(dir, dcl); /* Table start cluster */ + dj.fs->wflag = 1; + res = sync(dj.fs); + } + } + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Attribute */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chmod ( + const TCHAR *path, /* Pointer to the file path */ + BYTE value, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + FREE_BUF(); + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_OK) { + dir = dj.dir; + if (!dir) { /* Is it a root directory? */ + res = FR_INVALID_NAME; + } else { /* File or sub directory */ + mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ + dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + dj.fs->wflag = 1; + res = sync(dj.fs); + } + } + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Timestamp */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_utime ( + const TCHAR *path, /* Pointer to the file/directory name */ + const FILINFO *fno /* Pointer to the time stamp to be set */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + FREE_BUF(); + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_OK) { + dir = dj.dir; + if (!dir) { /* Root directory */ + res = FR_INVALID_NAME; + } else { /* File or sub-directory */ + ST_WORD(dir+DIR_WrtTime, fno->ftime); + ST_WORD(dir+DIR_WrtDate, fno->fdate); + dj.fs->wflag = 1; + res = sync(dj.fs); + } + } + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Rename File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_rename ( + const TCHAR *path_old, /* Pointer to the old name */ + const TCHAR *path_new /* Pointer to the new name */ +) +{ + FRESULT res; + DIR djo, djn; + BYTE buf[21], *dir; + DWORD dw; + DEF_NAMEBUF; + + + res = chk_mounted(&path_old, &djo.fs, 1); + if (res == FR_OK) { + djn.fs = djo.fs; + INIT_BUF(djo); + res = follow_path(&djo, path_old); /* Check old object */ + if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; +#if _FS_SHARE + if (res == FR_OK) res = chk_lock(&djo, 2); +#endif + if (res == FR_OK) { /* Old object is found */ + if (!djo.dir) { /* Is root dir? */ + res = FR_NO_FILE; + } else { + mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ + mem_cpy(&djn, &djo, sizeof(DIR)); /* Check new object */ + res = follow_path(&djn, path_new); + if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ + if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ +/* Start critical section that any interruption or error can cause cross-link */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + dir = djn.dir; /* Copy object information except for name */ + mem_cpy(dir+13, buf+2, 19); + dir[DIR_Attr] = buf[0] | AM_ARC; + djo.fs->wflag = 1; + if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ + dw = clust2sect(djn.fs, LD_CLUST(dir)); + if (!dw) { + res = FR_INT_ERR; + } else { + res = move_window(djn.fs, dw); + dir = djn.fs->win+SZ_DIR; /* .. entry */ + if (res == FR_OK && dir[1] == '.') { + dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust; + ST_CLUST(dir, dw); + djn.fs->wflag = 1; + } + } + } + if (res == FR_OK) { + res = dir_remove(&djo); /* Remove old entry */ + if (res == FR_OK) + res = sync(djo.fs); + } + } +/* End critical section */ + } + } + } + FREE_BUF(); + } + LEAVE_FF(djo.fs, res); +} + +#endif /* !_FS_READONLY */ +#endif /* _FS_MINIMIZE == 0 */ +#endif /* _FS_MINIMIZE <= 1 */ +#endif /* _FS_MINIMIZE <= 2 */ + + + +/*-----------------------------------------------------------------------*/ +/* Forward data to the stream directly (available on only tiny cfg) */ +/*-----------------------------------------------------------------------*/ +#if _USE_FORWARD && _FS_TINY + +FRESULT f_forward ( + FIL *fp, /* Pointer to the file object */ + UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ + UINT btr, /* Number of bytes to forward */ + UINT *bf /* Pointer to number of bytes forwarded */ +) +{ + FRESULT res; + DWORD remain, clst, sect; + UINT rcnt; + BYTE csect; + + + *bf = 0; /* Initialize byte counter */ + + res = validate(fp->fs, fp->id); /* Check validity of the object */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Check error flag */ + LEAVE_FF(fp->fs, FR_INT_ERR); + if (!(fp->flag & FA_READ)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + + remain = fp->fsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ + fp->fptr += rcnt, *bf += rcnt, btr -= rcnt) { + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + if (!csect) { /* On the cluster boundary? */ + clst = (fp->fptr == 0) ? /* On the top of the file? */ + fp->sclust : get_fat(fp->fs, fp->clust); + if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + } + sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + if (move_window(fp->fs, sect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + fp->dsect = sect; + rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */ + if (rcnt > btr) rcnt = btr; + rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt); + if (!rcnt) ABORT(fp->fs, FR_INT_ERR); + } + + LEAVE_FF(fp->fs, FR_OK); +} +#endif /* _USE_FORWARD */ + + + +#if _USE_MKFS && !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Create File System on the Drive */ +/*-----------------------------------------------------------------------*/ +#define N_ROOTDIR 512 /* Number of root dir entries for FAT12/16 */ +#define N_FATS 1 /* Number of FAT copies (1 or 2) */ + + +FRESULT f_mkfs ( + BYTE drv, /* Logical drive number */ + BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ + UINT au /* Allocation unit size [bytes] */ +) +{ + static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; + static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; + BYTE fmt, md, sys, *tbl, pdrv, part; + DWORD n_clst, vs, n, wsect; + UINT i; + DWORD b_vol, b_fat, b_dir, b_data; /* LBA */ + DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ + FATFS *fs; + DSTATUS stat; + + + /* Check mounted drive and clear work area */ + if (drv >= _VOLUMES) return FR_INVALID_DRIVE; + if (sfd > 1) return FR_INVALID_PARAMETER; + if (au & (au - 1)) return FR_INVALID_PARAMETER; + fs = FatFs[drv]; + if (!fs) return FR_NOT_ENABLED; + fs->fs_type = 0; + pdrv = LD2PD(drv); /* Physical drive */ + part = LD2PT(drv); /* Partition (0:auto detect, 1-4:get from partition table)*/ + + /* Get disk statics */ + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; +#if _MAX_SS != 512 /* Get disk sector size */ + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) + return FR_DISK_ERR; +#endif + if (_MULTI_PARTITION && part) { + /* Get partition information from partition table in the MBR */ + if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; + if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */ + b_vol = LD_DWORD(tbl+8); /* Volume start sector */ + n_vol = LD_DWORD(tbl+12); /* Volume size */ + } else { + /* Create a partition in this function */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) + return FR_DISK_ERR; + b_vol = (sfd) ? 0 : 63; /* Volume start sector */ + n_vol -= b_vol; /* Volume size */ + } + + if (!au) { /* AU auto selection */ + vs = n_vol / (2000 / (SS(fs) / 512)); + for (i = 0; vs < vst[i]; i++) ; + au = cst[i]; + } + au /= SS(fs); /* Number of sectors per cluster */ + if (au == 0) au = 1; + if (au > 128) au = 128; + + /* Pre-compute number of clusters and FAT syb-type */ + n_clst = n_vol / au; + fmt = FS_FAT12; + if (n_clst >= MIN_FAT16) fmt = FS_FAT16; + if (n_clst >= MIN_FAT32) fmt = FS_FAT32; + + /* Determine offset and size of FAT structure */ + if (fmt == FS_FAT32) { + n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); + n_rsv = 32; + n_dir = 0; + } else { + n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; + n_fat = (n_fat + SS(fs) - 1) / SS(fs); + n_rsv = 1; + n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs); + } + b_fat = b_vol + n_rsv; /* FAT area start sector */ + b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ + b_data = b_dir + n_dir; /* Data area start sector */ + if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ + + /* Align data start sector to erase block boundary (for flash memory media) */ + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; + n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ + n = (n - b_data) / N_FATS; + if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ + n_rsv += n; + b_fat += n; + } else { /* FAT12/16: Expand FAT size */ + n_fat += n; + } + + /* Determine number of clusters and final check of validity of the FAT sub-type */ + n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; + if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) + || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) + return FR_MKFS_ABORTED; + + switch (fmt) { /* Determine system ID for partition table */ + case FS_FAT12: sys = 0x01; break; + case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break; + default: sys = 0x0C; + } + + if (_MULTI_PARTITION && part) { + /* Update system ID in the partition table */ + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + tbl[4] = sys; + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; + md = 0xF8; + } else { + if (sfd) { /* No patition table (SFD) */ + md = 0xF0; + } else { /* Create partition table (FDISK) */ + mem_set(fs->win, 0, SS(fs)); + tbl = fs->win+MBR_Table; /* Create partiton table for single partition in the drive */ + tbl[1] = 1; /* Partition start head */ + tbl[2] = 1; /* Partition start sector */ + tbl[3] = 0; /* Partition start cylinder */ + tbl[4] = sys; /* System type */ + tbl[5] = 254; /* Partition end head */ + n = (b_vol + n_vol) / 63 / 255; + tbl[6] = (BYTE)((n >> 2) | 63); /* Partiiton end sector */ + tbl[7] = (BYTE)n; /* End cylinder */ + ST_DWORD(tbl+8, 63); /* Partition start in LBA */ + ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ + ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */ + return FR_DISK_ERR; + md = 0xF8; + } + } + + /* Create BPB in the VBR */ + tbl = fs->win; /* Clear sector */ + mem_set(tbl, 0, SS(fs)); + mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */ + i = SS(fs); /* Sector size */ + ST_WORD(tbl+BPB_BytsPerSec, i); + tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ + ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ + tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ + i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ + ST_WORD(tbl+BPB_RootEntCnt, i); + if (n_vol < 0x10000) { /* Number of total sectors */ + ST_WORD(tbl+BPB_TotSec16, n_vol); + } else { + ST_DWORD(tbl+BPB_TotSec32, n_vol); + } + tbl[BPB_Media] = md; /* Media descriptor */ + ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ + ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ + ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ + n = get_fattime(); /* Use current time as VSN */ + if (fmt == FS_FAT32) { + ST_DWORD(tbl+BS_VolID32, n); /* VSN */ + ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ + ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ + ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */ + ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ + tbl[BS_DrvNum32] = 0x80; /* Drive number */ + tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ + } else { + ST_DWORD(tbl+BS_VolID, n); /* VSN */ + ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ + tbl[BS_DrvNum] = 0x80; /* Drive number */ + tbl[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + } + ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ + if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */ + return FR_DISK_ERR; + if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */ + disk_write(pdrv, tbl, b_vol + 6, 1); + + /* Initialize FAT area */ + wsect = b_fat; + for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */ + mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ + n = md; /* Media descriptor byte */ + if (fmt != FS_FAT32) { + n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; + ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */ + } else { + n |= 0xFFFFFF00; + ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */ + ST_DWORD(tbl+4, 0xFFFFFFFF); + ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ + } + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) + return FR_DISK_ERR; + mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ + for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) + return FR_DISK_ERR; + } + } + + /* Initialize root directory */ + i = (fmt == FS_FAT32) ? au : n_dir; + do { + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) + return FR_DISK_ERR; + } while (--i); + +#if _USE_ERASE /* Erase data area if needed */ + { + DWORD eb[2]; + + eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; + disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb); + } +#endif + + /* Create FSInfo if needed */ + if (fmt == FS_FAT32) { + ST_DWORD(tbl+FSI_LeadSig, 0x41615252); + ST_DWORD(tbl+FSI_StrucSig, 0x61417272); + ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */ + ST_WORD(tbl+BS_55AA, 0xAA55); + disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ + disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ + } + + return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; +} + + +#if _MULTI_PARTITION == 2 +/*-----------------------------------------------------------------------*/ +/* Divide Physical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const DWORD szt[], /* Pointer to the size table for each partitions */ + void* work /* Pointer to the working buffer */ +) +{ + UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; + DSTATUS stat; + DWORD sz_disk, sz_part, s_part; + + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; + + /* Determine CHS in the table regardless of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + if (n == 256) n--; + e_hd = n - 1; + sz_cyl = 63 * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + mem_set(buf, 0, _MAX_SS); + p = buf + MBR_Table; b_cyl = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) { + p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; + if (!p_cyl) continue; + s_part = (DWORD)sz_cyl * b_cyl; + sz_part = (DWORD)sz_cyl * p_cyl; + if (i == 0) { /* Exclude first track of cylinder 0 */ + s_hd = 1; + s_part += 63; sz_part -= 63; + } else { + s_hd = 0; + } + e_cyl = b_cyl + p_cyl - 1; + if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x06; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + ST_DWORD(p + 8, s_part); /* Start sector in LBA */ + ST_DWORD(p + 12, sz_part); /* Partition size */ + + /* Next partition */ + b_cyl += p_cyl; + } + ST_WORD(p, 0xAA55); + + /* Write it to the MBR */ + return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK; +} + + +#endif /* _MULTI_PARTITION == 2 */ +#endif /* _USE_MKFS && !_FS_READONLY */ + + + + +#if _USE_STRFUNC +/*-----------------------------------------------------------------------*/ +/* Get a string from the file */ +/*-----------------------------------------------------------------------*/ +TCHAR* f_gets ( + TCHAR* buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (characters) */ + FIL* fil /* Pointer to the file object */ +) +{ + int n = 0; + TCHAR c, *p = buff; + BYTE s[2]; + UINT rc; + + + while (n < len - 1) { /* Read bytes until buffer gets filled */ + f_read(fil, s, 1, &rc); + if (rc != 1) break; /* Break on EOF or error */ + c = s[0]; +#if _LFN_UNICODE /* Read a character in UTF-8 encoding */ + if (c >= 0x80) { + if (c < 0xC0) continue; /* Skip stray trailer */ + if (c < 0xE0) { /* Two-byte sequense */ + f_read(fil, s, 1, &rc); + if (rc != 1) break; + c = ((c & 0x1F) << 6) | (s[0] & 0x3F); + if (c < 0x80) c = '?'; + } else { + if (c < 0xF0) { /* Three-byte sequense */ + f_read(fil, s, 2, &rc); + if (rc != 2) break; + c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F); + if (c < 0x800) c = '?'; + } else { /* Reject four-byte sequense */ + c = '?'; + } + } + } +#endif +#if _USE_STRFUNC >= 2 + if (c == '\r') continue; /* Strip '\r' */ +#endif + *p++ = c; + n++; + if (c == '\n') break; /* Break on EOL */ + } + *p = 0; + return n ? buff : 0; /* When no data read (eof or error), return with error. */ +} + + + +#if !_FS_READONLY +#include +/*-----------------------------------------------------------------------*/ +/* Put a character to the file */ +/*-----------------------------------------------------------------------*/ +int f_putc ( + TCHAR c, /* A character to be output */ + FIL* fil /* Pointer to the file object */ +) +{ + UINT bw, btw; + BYTE s[3]; + + +#if _USE_STRFUNC >= 2 + if (c == '\n') f_putc ('\r', fil); /* LF -> CRLF conversion */ +#endif + +#if _LFN_UNICODE /* Write the character in UTF-8 encoding */ + if (c < 0x80) { /* 7-bit */ + s[0] = (BYTE)c; + btw = 1; + } else { + if (c < 0x800) { /* 11-bit */ + s[0] = (BYTE)(0xC0 | (c >> 6)); + s[1] = (BYTE)(0x80 | (c & 0x3F)); + btw = 2; + } else { /* 16-bit */ + s[0] = (BYTE)(0xE0 | (c >> 12)); + s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F)); + s[2] = (BYTE)(0x80 | (c & 0x3F)); + btw = 3; + } + } +#else /* Write the character without conversion */ + s[0] = (BYTE)c; + btw = 1; +#endif + f_write(fil, s, btw, &bw); /* Write the char to the file */ + return (bw == btw) ? 1 : EOF; /* Return the result */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a string to the file */ +/*-----------------------------------------------------------------------*/ +int f_puts ( + const TCHAR* str, /* Pointer to the string to be output */ + FIL* fil /* Pointer to the file object */ +) +{ + int n; + + + for (n = 0; *str; str++, n++) { + if (f_putc(*str, fil) == EOF) return EOF; + } + return n; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a formatted string to the file */ +/*-----------------------------------------------------------------------*/ +int f_printf ( + FIL* fil, /* Pointer to the file object */ + const TCHAR* str, /* Pointer to the format string */ + ... /* Optional arguments... */ +) +{ + va_list arp; + BYTE f, r; + UINT i, j, w; + ULONG v; + TCHAR c, d, s[16], *p; + int res, chc, cc; + + + va_start(arp, str); + + for (cc = res = 0; cc != EOF; res += cc) { + c = *str++; + if (c == 0) break; /* End of string */ + if (c != '%') { /* Non escape character */ + cc = f_putc(c, fil); + if (cc != EOF) cc = 1; + continue; + } + w = f = 0; + c = *str++; + if (c == '0') { /* Flag: '0' padding */ + f = 1; c = *str++; + } else { + if (c == '-') { /* Flag: left justified */ + f = 2; c = *str++; + } + } + while (IsDigit(c)) { /* Precision */ + w = w * 10 + c - '0'; + c = *str++; + } + if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ + f |= 4; c = *str++; + } + if (!c) break; + d = c; + if (IsLower(d)) d -= 0x20; + switch (d) { /* Type is... */ + case 'S' : /* String */ + p = va_arg(arp, TCHAR*); + for (j = 0; p[j]; j++) ; + chc = 0; + if (!(f & 2)) { + while (j++ < w) chc += (cc = f_putc(' ', fil)); + } + chc += (cc = f_puts(p, fil)); + while (j++ < w) chc += (cc = f_putc(' ', fil)); + if (cc != EOF) cc = chc; + continue; + case 'C' : /* Character */ + cc = f_putc((TCHAR)va_arg(arp, int), fil); continue; + case 'B' : /* Binary */ + r = 2; break; + case 'O' : /* Octal */ + r = 8; break; + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + case 'X' : /* Hexdecimal */ + r = 16; break; + default: /* Unknown type (passthrough) */ + cc = f_putc(c, fil); continue; + } + + /* Get an argument and put it in numeral */ + v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) { + v = 0 - v; + f |= 8; + } + i = 0; + do { + d = (TCHAR)(v % r); v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; + s[i++] = d + '0'; + } while (v && i < sizeof(s) / sizeof(s[0])); + if (f & 8) s[i++] = '-'; + j = i; d = (f & 1) ? '0' : ' '; + res = 0; + while (!(f & 2) && j++ < w) res += (cc = f_putc(d, fil)); + do res += (cc = f_putc(s[--i], fil)); while(i); + while (j++ < w) res += (cc = f_putc(' ', fil)); + if (cc != EOF) cc = res; + } + + va_end(arp); + return (cc == EOF) ? cc : res; +} + +#endif /* !_FS_READONLY */ +#endif /* _USE_STRFUNC */ diff --git a/lib/src/common/_FAT32_/fat32.h b/lib/src/common/_FAT32_/fat32.h new file mode 100644 --- /dev/null +++ b/lib/src/common/_FAT32_/fat32.h @@ -0,0 +1,340 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module include file R0.09 (C)ChaN, 2011 +/----------------------------------------------------------------------------/ +/ FatFs module is a generic FAT file system module for small embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following trems. +/ +/ Copyright (C) 2011, ChaN, all right reserved. +/ +/ * The FatFs module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/----------------------------------------------------------------------------*/ + +#ifndef _FATFS +#define _FATFS 6502 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" /* Basic integer types */ +#include "ffconf.h" /* FatFs configuration options */ +#include + +#if _FATFS != _FFCONF +#error Wrong configuration file (ffconf.h). +#endif + + + +/* Definitions of volume management */ + +#if _MULTI_PARTITION /* Multiple partition configuration */ +typedef struct { + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ +} PARTITION; +extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ +#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ +#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ + +#else /* Single partition configuration */ +#define LD2PD(vol) (vol) /* Each logical drive is bound to the same physical drive number */ +#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */ + +#endif + + + +/* Type of path name strings on FatFs API */ + +#if _LFN_UNICODE /* Unicode string */ +#if !_USE_LFN +#error _LFN_UNICODE must be 0 in non-LFN cfg. +#endif +#ifndef _INC_TCHAR +typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#endif + +#else /* ANSI/OEM string */ +#ifndef _INC_TCHAR +typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif + +#endif + + + +/* File system object structure (FATFS) */ + +typedef struct { + BYTE fs_type; /* FAT sub-type (0:Not mounted) */ + BYTE csize; /* Sectors per cluster (1,2,4...128) */ + BYTE n_fats; /* Number of FAT copies (1,2) */ + BYTE wflag; /* win[] dirty flag (1:must be written back) */ + BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ + /*AJE 01/06/2012*/ + //BYTE drv; /* Physical drive number */ + blkdevice* drv; + WORD id; /* File system mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ +#if _MAX_SS != 512 + WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ +#endif +#if _FS_REENTRANT + _SYNC_t sobj; /* Identifier of sync object */ +#endif +#if !_FS_READONLY + DWORD last_clust; /* Last allocated cluster */ + DWORD free_clust; /* Number of free clusters */ + DWORD fsi_sector; /* fsinfo sector (FAT32) */ +#endif +#if _FS_RPATH + DWORD cdir; /* Current directory start cluster (0:root) */ +#endif + DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ + DWORD fsize; /* Sectors per FAT */ + DWORD fatbase; /* FAT start sector */ + DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ + DWORD database; /* Data start sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ +} FATFS; + + + +/* File object structure (FIL) */ + +typedef struct { + FATFS* fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + BYTE flag; /* File status flags */ + BYTE pad1; + DWORD fptr; /* File read/write pointer (0 on file open) */ + DWORD fsize; /* File size */ + DWORD sclust; /* File start cluster (0 when fsize==0) */ + DWORD clust; /* Current cluster */ + DWORD dsect; /* Current data sector */ +#if !_FS_READONLY + DWORD dir_sect; /* Sector containing the directory entry */ + BYTE* dir_ptr; /* Ponter to the directory entry in the window */ +#endif +#if _USE_FASTSEEK + DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ +#endif +#if _FS_SHARE + UINT lockid; /* File lock ID (index of file semaphore table) */ +#endif +#if !_FS_TINY + BYTE buf[_MAX_SS]; /* File data read/write buffer */ +#endif +} FIL; + + + +/* Directory object structure (DIR) */ + +typedef struct { + FATFS* fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + WORD index; /* Current read/write index number */ + DWORD sclust; /* Table start cluster (0:Root dir) */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector */ + BYTE* dir; /* Pointer to the current SFN entry in the win[] */ + BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ +#if _USE_LFN + WCHAR* lfn; /* Pointer to the LFN working buffer */ + WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ +#endif +} DIR; + + + +/* File status structure (FILINFO) */ + +typedef struct { + DWORD fsize; /* File size */ + WORD fdate; /* Last modified date */ + WORD ftime; /* Last modified time */ + BYTE fattrib; /* Attribute */ + TCHAR fname[13]; /* Short file name (8.3 format) */ +#if _USE_LFN + TCHAR* lfname; /* Pointer to the LFN buffer */ + UINT lfsize; /* Size of LFN buffer in TCHAR */ +#endif +} FILINFO; + + + +/* File function return code (FRESULT) */ + +typedef enum { + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Acces denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ +} FRESULT; + + + +/*--------------------------------------------------------------*/ +/* FatFs module application interface */ + +FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */ +FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */ +FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */ +FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */ +FRESULT f_close (FIL*); /* Close an open file object */ +FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */ +FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */ +FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */ +FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */ +FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ +FRESULT f_truncate (FIL*); /* Truncate file */ +FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ +FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */ +FRESULT f_mkdir (const TCHAR*); /* Create a new directory */ +FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */ +FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */ +FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */ +FRESULT f_chdrive (BYTE); /* Change current drive */ +FRESULT f_chdir (const TCHAR*); /* Change current directory */ +FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */ +FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ +FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ +FRESULT f_fdisk (BYTE, const DWORD[], void*); /* Divide a physical drive into some partitions */ +int f_putc (TCHAR, FIL*); /* Put a character to the file */ +int f_puts (const TCHAR*, FIL*); /* Put a string to the file */ +int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */ +TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ + +#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) +#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->fsize) + +#ifndef EOF +#define EOF (-1) +#endif + + + + +/*--------------------------------------------------------------*/ +/* Additional user defined functions */ + +/* RTC function */ +#if !_FS_READONLY +DWORD get_fattime (void); +#endif + +/* Unicode support functions */ +#if _USE_LFN /* Unicode - OEM code conversion */ +WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */ +WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */ +#if _USE_LFN == 3 /* Memory functions */ +void* ff_memalloc (UINT); /* Allocate memory block */ +void ff_memfree (void*); /* Free memory block */ +#endif +#endif + +/* Sync functions */ +#if _FS_REENTRANT +int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */ +int ff_req_grant (_SYNC_t); /* Lock sync object */ +void ff_rel_grant (_SYNC_t); /* Unlock sync object */ +int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ +#endif + + + + +/*--------------------------------------------------------------*/ +/* Flags and offset address */ + + +/* File access control and file status flags (FIL.flag) */ + +#define FA_READ 0x01 +#define FA_OPEN_EXISTING 0x00 +#define FA__ERROR 0x80 + +#if !_FS_READONLY +#define FA_WRITE 0x02 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA__WRITTEN 0x20 +#define FA__DIRTY 0x40 +#endif + + +/* FAT sub type (FATFS.fs_type) */ + +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 + + +/* File attribute bits for directory entry */ + +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ +#define AM_MASK 0x3F /* Mask of defined bits */ + + +/* Fast seek feature */ +#define CREATE_LINKMAP 0xFFFFFFFF + + + +/*--------------------------------*/ +/* Multi-byte word access macros */ + +#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) +#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) +#else /* Use byte-by-byte access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) +#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _FATFS */ diff --git a/lib/src/common/_FAT32_/fat32.pro b/lib/src/common/_FAT32_/fat32.pro new file mode 100644 --- /dev/null +++ b/lib/src/common/_FAT32_/fat32.pro @@ -0,0 +1,26 @@ +TEMPLATE = lib +lpc17XX.ARCH = lpc17XX-arm-noabi-gcc +lpc17XX.TARGET = libfat32 +lpc17XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_FAT32) +lpc17XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FAT32) + +lpc17XX.LIBS += BLKDEVICE + +lpc17XX.SOURCES += fat32.c + + +lpc17XX.HEADERS += fat32.h + + + +lpc21XX.ARCH = lpc21XX-arm-noabi-gcc +lpc21XX.TARGET = libfat32 +lpc21XX.TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_FAT32) +lpc21XX.HEADERSINSTALLPATH = $(LIBUC_INC_DIR_FAT32) + +lpc21XX.LIBS += BLKDEVICE + +lpc21XX.SOURCES += fat32.c + + +lpc21XX.HEADERS += fat32.h diff --git a/lib/src/common/_FAT32_/ffconf.h b/lib/src/common/_FAT32_/ffconf.h new file mode 100644 --- /dev/null +++ b/lib/src/common/_FAT32_/ffconf.h @@ -0,0 +1,190 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module configuration file R0.09 (C)ChaN, 2011 +/----------------------------------------------------------------------------/ +/ +/ CAUTION! Do not forget to make clean the project after any changes to +/ the configuration options. +/ +/----------------------------------------------------------------------------*/ +#ifndef _FFCONF +#define _FFCONF 6502 /* Revision ID */ + + +/*---------------------------------------------------------------------------/ +/ Functions and Buffer Configurations +/----------------------------------------------------------------------------*/ + +#define _FS_TINY 0 /* 0:Normal or 1:Tiny */ +/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system +/ object instead of the sector buffer in the individual file object for file +/ data transfer. This reduces memory consumption 512 bytes each file object. */ + + +#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ +/* Setting _FS_READONLY to 1 defines read only configuration. This removes +/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, +/ f_truncate and useless f_getfree. */ + + +#define _FS_MINIMIZE 0 /* 0 to 3 */ +/* The _FS_MINIMIZE option defines minimization level to remove some functions. +/ +/ 0: Full function. +/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename +/ are removed. +/ 2: f_opendir and f_readdir are removed in addition to 1. +/ 3: f_lseek is removed in addition to 2. */ + + +#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */ +/* To enable string functions, set _USE_STRFUNC to 1 or 2. */ + + +#define _USE_MKFS 0 /* 0:Disable or 1:Enable */ +/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ + + +#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ +/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ + + +#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ +/* To enable fast seek feature, set _USE_FASTSEEK to 1. */ + + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/----------------------------------------------------------------------------*/ + +#define _CODE_PAGE 932 +/* The _CODE_PAGE specifies the OEM code page to be used on the target system. +/ Incorrect setting of the code page can cause a file open failure. +/ +/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows) +/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows) +/ 949 - Korean (DBCS, OEM, Windows) +/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) +/ 1250 - Central Europe (Windows) +/ 1251 - Cyrillic (Windows) +/ 1252 - Latin 1 (Windows) +/ 1253 - Greek (Windows) +/ 1254 - Turkish (Windows) +/ 1255 - Hebrew (Windows) +/ 1256 - Arabic (Windows) +/ 1257 - Baltic (Windows) +/ 1258 - Vietnam (OEM, Windows) +/ 437 - U.S. (OEM) +/ 720 - Arabic (OEM) +/ 737 - Greek (OEM) +/ 775 - Baltic (OEM) +/ 850 - Multilingual Latin 1 (OEM) +/ 858 - Multilingual Latin 1 + Euro (OEM) +/ 852 - Latin 2 (OEM) +/ 855 - Cyrillic (OEM) +/ 866 - Russian (OEM) +/ 857 - Turkish (OEM) +/ 862 - Hebrew (OEM) +/ 874 - Thai (OEM, Windows) +/ 1 - ASCII only (Valid for non LFN cfg.) +*/ + + +#define _USE_LFN 0 /* 0 to 3 */ +#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ +/* The _USE_LFN option switches the LFN support. +/ +/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN, +/ Unicode handling functions ff_convert() and ff_wtoupper() must be added +/ to the project. When enable to use heap, memory control functions +/ ff_memalloc() and ff_memfree() must be added to the project. */ + + +#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ +/* To switch the character code set on FatFs API to Unicode, +/ enable LFN feature and set _LFN_UNICODE to 1. */ + + +#define _FS_RPATH 0 /* 0 to 2 */ +/* The _FS_RPATH option configures relative path feature. +/ +/ 0: Disable relative path feature and remove related functions. +/ 1: Enable relative path. f_chdrive() and f_chdir() are available. +/ 2: f_getcwd() is available in addition to 1. +/ +/ Note that output of the f_readdir fnction is affected by this option. */ + + + +/*---------------------------------------------------------------------------/ +/ Physical Drive Configurations +/----------------------------------------------------------------------------*/ + +#define _VOLUMES 1 +/* Number of volumes (logical drives) to be used. */ + + +#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ +/* Maximum sector size to be handled. +/ Always set 512 for memory card and hard disk but a larger value may be +/ required for on-board flash memory, floppy disk and optical disk. +/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size +/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */ + + +#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */ +/* When set to 0, each volume is bound to the same physical drive number and +/ it can mount only first primaly partition. When it is set to 1, each volume +/ is tied to the partitions listed in VolToPart[]. */ + + +#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ +/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command +/ should be added to the disk_ioctl functio. */ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/----------------------------------------------------------------------------*/ + +#define _WORD_ACCESS 0 /* 0 or 1 */ +/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS +/ option defines which access method is used to the word data on the FAT volume. +/ +/ 0: Byte-by-byte access. +/ 1: Word access. Do not choose this unless following condition is met. +/ +/ When the byte order on the memory is big-endian or address miss-aligned word +/ access results incorrect behavior, the _WORD_ACCESS must be set to 0. +/ If it is not the case, the value can also be set to 1 to improve the +/ performance and code size. +*/ + + +/* A header file that defines sync object types on the O/S, such as +/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */ + +#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ +#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ +#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ + +/* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module. +/ +/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. +/ 1: Enable reentrancy. Also user provided synchronization handlers, +/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj +/ function must be added to the project. */ + + +#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ +/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value + defines how many files can be opened simultaneously. */ + + +#endif /* _FFCONFIG */ diff --git a/lib/src/common/_FAT32_/integer.h b/lib/src/common/_FAT32_/integer.h new file mode 100644 --- /dev/null +++ b/lib/src/common/_FAT32_/integer.h @@ -0,0 +1,37 @@ +/*-------------------------------------------*/ +/* Integer type definitions for FatFs module */ +/*-------------------------------------------*/ + +#ifndef _INTEGER +#define _INTEGER + +#ifdef _WIN32 /* FatFs development platform */ + +#include +#include + +#else /* Embedded platform */ + +/* These types must be 16-bit, 32-bit or larger integer */ +typedef int INT; +typedef unsigned int UINT; + +/* These types must be 8-bit integer */ +typedef char CHAR; +typedef unsigned char UCHAR; +typedef unsigned char BYTE; + +/* These types must be 16-bit integer */ +typedef short SHORT; +typedef unsigned short USHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types must be 32-bit integer */ +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long DWORD; + +#endif + +#endif diff --git a/lib/src/common/common.pro b/lib/src/common/common.pro --- a/lib/src/common/common.pro +++ b/lib/src/common/common.pro @@ -1,6 +1,6 @@ TEMPLATE = dir -SUBDIRS += 24LCXX \ - STRINGS \ +SUBDIRS += STRINGS \ + HEXVIEWER \ + 24LCXX \ VS10XX \ - SDCARD \ - BLOCKDEVICES + FILE_SYSTEM diff --git a/lib/src/lib.pro b/lib/src/lib.pro --- a/lib/src/lib.pro +++ b/lib/src/lib.pro @@ -1,6 +1,8 @@ TEMPLATE = dir -SUBDIRS += lpc21XX \ +SUBDIRS += common/UHANDLE \ + lpc21XX \ lpc17XX \ LEON3 \ - common + common \ + apps diff --git a/lib/src/lpc17XX/CORE/Makefile b/lib/src/lpc17XX/CORE/Makefile --- a/lib/src/lpc17XX/CORE/Makefile +++ b/lib/src/lpc17XX/CORE/Makefile @@ -5,7 +5,10 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_INC_DIR)/CORE HEADERS += core.h LIBSOURCES += core.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc17XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc TARGET=libcore @@ -18,3 +21,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/lpc17XX/IIC/Makefile b/lib/src/lpc17XX/IIC/Makefile --- a/lib/src/lpc17XX/IIC/Makefile +++ b/lib/src/lpc17XX/IIC/Makefile @@ -5,12 +5,15 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_INC_DIR_IIC) HEADERS += iic.h LIBSOURCES += iic.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc17XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc TARGET=libiic -LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) -LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) +LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_IIC) HEADERSINSTALLPATH=$(LIBUC_INC_DIR_IIC) BSP=generic @@ -18,3 +21,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/lpc17XX/IIC/iic.c b/lib/src/lpc17XX/IIC/iic.c --- a/lib/src/lpc17XX/IIC/iic.c +++ b/lib/src/lpc17XX/IIC/iic.c @@ -22,29 +22,27 @@ #include "iic.h" #include "core.h" -#define iicputdata(iicdev,W,IICONSET,IICONCLR) {(iicdev)->I2DAT = (W);\ - (iicdev)->I2CONSET = (IICONSET);\ - (iicdev)->I2CONCLR = (IICONCLR);} +#define iicputdata(iicdev,W,IICONSET,IICONCLR) {((_i2cDev)(iicdev))->I2DAT = (W);\ + ((_i2cDev)(iicdev))->I2CONSET = (IICONSET);\ + ((_i2cDev)(iicdev))->I2CONCLR = (IICONCLR);} -#define iicgetdata(iicdev,W,IICONSET,IICONCLR) {(W) = (iicdev)->I2DAT;\ - (iicdev)->I2CONSET = (IICONSET);\ - (iicdev)->I2CONCLR = (IICONCLR);} +#define iicgetdata(iicdev,W,IICONSET,IICONCLR) {(W) = ((_i2cDev)(iicdev))->I2DAT;\ + ((_i2cDev)(iicdev))->I2CONSET = (IICONSET);\ + ((_i2cDev)(iicdev))->I2CONCLR = (IICONCLR);} - - -i2ctrl i2cwrite2(i2cDev* dev,char address,char*cmd,int* cmdcnt,char*data,int* datcnt) +i2ctrl i2cwrite2(i2cDev dev,char address,char*cmd,int* cmdcnt,char*data,int* datcnt) { char iicdat=0; - dev->I2CONCLR = 0x28; + ((_i2cDev)dev)->I2CONCLR = 0x28; iicdat = (address<<1) & 0xFE; int count = (*datcnt) + 2; (*datcnt) = 0; - while(dev->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout - dev->I2CONSET = (1<<5); //initiate transfert + while(((_i2cDev)dev)->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout + ((_i2cDev)dev)->I2CONSET = (1<<5); //initiate transfert while(count>0) { - while((dev->I2CONSET & 0x08)!=0x08); - switch(dev->I2STAT) + while((((_i2cDev)dev)->I2CONSET & 0x08)!=0x08); + switch(((_i2cDev)dev)->I2STAT) { case 0x08: iicputdata(dev,iicdat,(1<<2),0x28); @@ -99,26 +97,26 @@ i2ctrl i2cwrite2(i2cDev* dev,char addres } } - dev->I2CONSET = (1<<4) + (1<<2); - dev->I2CONCLR = 1<<3; + ((_i2cDev)dev)->I2CONSET = (1<<4) + (1<<2); + ((_i2cDev)dev)->I2CONCLR = 1<<3; return i2noerr; } -i2ctrl i2cwrite(i2cDev* dev,char address,char*data,int* cnt) +i2ctrl i2cwrite(i2cDev dev,char address,char*data,int* cnt) { char iicdat=0; - dev->I2CONCLR = 0x28; + ((_i2cDev)dev)->I2CONCLR = 0x28; iicdat = (address<<1) & 0xFE; int count = (*cnt) + 1; *cnt = 0; - while(dev->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout - dev->I2CONSET = (1<<5); //initiate transfert + while(((_i2cDev)dev)->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout + ((_i2cDev)dev)->I2CONSET = (1<<5); //initiate transfert while(count>0) { - while((dev->I2CONSET & 0x08)!=0x08); - switch(dev->I2STAT) + while((((_i2cDev)dev)->I2CONSET & 0x08)!=0x08); + switch(((_i2cDev)dev)->I2STAT) { case 0x08: iicputdata(dev,iicdat,(1<<2),0x28); @@ -156,27 +154,27 @@ i2ctrl i2cwrite(i2cDev* dev,char address } } - dev->I2CONSET = (1<<4) + (1<<2); - dev->I2CONCLR = 1<<3; + ((_i2cDev)dev)->I2CONSET = (1<<4) + (1<<2); + ((_i2cDev)dev)->I2CONCLR = 1<<3; return i2noerr; } -i2ctrl i2cread(i2cDev* dev,char address,char*data,int* cnt) +i2ctrl i2cread(i2cDev dev,char address,char*data,int* cnt) { char iicdat=0; - dev->I2CONCLR = 0x28; + ((_i2cDev)dev)->I2CONCLR = 0x28; iicdat = (address<<1) + 1; unsigned int count = (*cnt); *cnt = 0; - while(dev->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout - dev->I2CONSET = (1<<5); //initiate transfert + while(((_i2cDev)dev)->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout + ((_i2cDev)dev)->I2CONSET = (1<<5); //initiate transfert while(count!=0) { - while((dev->I2CONSET & 0x08)!=0x08); - switch(dev->I2STAT) + while((((_i2cDev)dev)->I2CONSET & 0x08)!=0x08); + switch(((_i2cDev)dev)->I2STAT) { - while((dev->I2CONSET & (1<<3))!=(1<<3)); + while((((_i2cDev)dev)->I2CONSET & (1<<3))!=(1<<3)); case 0x08: iicputdata(dev,iicdat,(1<<2),0x28); break; @@ -184,9 +182,9 @@ i2ctrl i2cread(i2cDev* dev,char address, iicputdata(dev,iicdat,(1<<2),0x28); break; case 0x40: - if((count!=1)) dev->I2CONSET = (1<<2); - else dev->I2CONCLR = (1<<2); - dev->I2CONCLR = 1<<3; + if((count!=1)) ((_i2cDev)dev)->I2CONSET = (1<<2); + else ((_i2cDev)dev)->I2CONCLR = (1<<2); + ((_i2cDev)dev)->I2CONCLR = 1<<3; break; case 0x50: if((count==2)) iicgetdata(dev,iicdat,(0),(0x0c)) @@ -197,8 +195,8 @@ i2ctrl i2cread(i2cDev* dev,char address, data++; break; case 0x48: - dev->I2CONSET = 0x14; - dev->I2CONCLR = 8; + ((_i2cDev)dev)->I2CONSET = 0x14; + ((_i2cDev)dev)->I2CONCLR = 8; return i2noerr; break; case 0x58: @@ -214,49 +212,50 @@ i2ctrl i2cread(i2cDev* dev,char address, } } - dev->I2CONSET = (1<<4); dev->I2CONCLR =(1<<2); - dev->I2CONCLR = 1<<3; + ((_i2cDev)dev)->I2CONSET = (1<<4); + ((_i2cDev)dev)->I2CONCLR =(1<<2); + ((_i2cDev)dev)->I2CONCLR = 1<<3; return i2noerr; } -void i2csetup(i2cDev* dev,int clkH,int clkL) +void i2csetup(i2cDev dev,int clkH,int clkL) { - dev->I2CONCLR = 0x6C; - dev->I2SCLH = clkH; - dev->I2SCLL = clkL; - dev->I2CONSET = 1<<6; //enable I2C block - dev->I2CONCLR = 0x28; + ((_i2cDev)dev)->I2CONCLR = 0x6C; + ((_i2cDev)dev)->I2SCLH = clkH; + ((_i2cDev)dev)->I2SCLL = clkL; + ((_i2cDev)dev)->I2CONSET = 1<<6; //enable I2C block + ((_i2cDev)dev)->I2CONCLR = 0x28; } -void i2cenable(i2cDev* dev) +void i2cenable(i2cDev dev) { - dev->I2CONSET = 1<<6; + ((_i2cDev)dev)->I2CONSET = 1<<6; } -void i2cdisable(i2cDev* dev) +void i2cdisable(i2cDev dev) { - dev->I2CONCLR = (1<<6); + ((_i2cDev)dev)->I2CONCLR = (1<<6); } -i2cDev* i2copen(int count){ - i2cDev* dev; +i2cDev i2copen(int count){ + i2cDev dev; switch(count) { case 0: - dev = (i2cDev*)((unsigned long)LPC_I2C0_BASE); + dev = (i2cDev)((unsigned long)LPC_I2C0_BASE); break; case 1: - dev = (i2cDev*)((unsigned long)LPC_I2C1_BASE); + dev = (i2cDev)((unsigned long)LPC_I2C1_BASE); break; case 2: - dev = (i2cDev*)((unsigned long)LPC_I2C2_BASE); + dev = (i2cDev)((unsigned long)LPC_I2C2_BASE); break; default: - dev = (i2cDev*)0; + dev = (i2cDev)0; break; } return dev; @@ -264,7 +263,7 @@ i2cDev* i2copen(int count){ -unsigned char i2cgetpclkfactor(i2cDev* dev) +unsigned char i2cgetpclkfactor(i2cDev dev) { unsigned int clksel=0; const char clkselDec[]={4,1,2,8}; @@ -286,7 +285,7 @@ unsigned char i2cgetpclkfactor(i2cDev* d } -void i2csetpclkfactor(i2cDev* dev,unsigned char pclkfactor) +void i2csetpclkfactor(i2cDev dev,unsigned char pclkfactor) { const char clkselDec[]={1,1,2,2,0,0,0,0,3}; unsigned int clksel=0; @@ -311,7 +310,7 @@ void i2csetpclkfactor(i2cDev* dev,unsign } -void i2csetdatarate(i2cDev* dev,unsigned int dataRate) +void i2csetdatarate(i2cDev dev,unsigned int dataRate) { unsigned int pclk = 0; unsigned int cpuclk=0; @@ -324,16 +323,16 @@ void i2csetdatarate(i2cDev* dev,unsigned i2csetup(dev,i2csclkl,i2csclkl); } -int i2cgetdatarate(i2cDev* dev) +int i2cgetdatarate(i2cDev dev) { unsigned int dataRate=0; unsigned int pclk = 0; unsigned int cpuclk=0; unsigned int i2csclkl=0; - if(dev==0)return; + if(dev==0)return 0; cpuclk = coregetCpuFreq(); pclk = cpuclk / i2cgetpclkfactor(dev); - dataRate = pclk /( dev->I2SCLH + dev->I2SCLL); + dataRate = pclk /( ((_i2cDev)dev)->I2SCLH + ((_i2cDev)dev)->I2SCLL); return dataRate; } diff --git a/lib/src/lpc17XX/IIC/iic.h b/lib/src/lpc17XX/IIC/iic.h --- a/lib/src/lpc17XX/IIC/iic.h +++ b/lib/src/lpc17XX/IIC/iic.h @@ -21,7 +21,9 @@ -------------------------------------------------------------------------------*/ #ifndef IIC_H #define IIC_H + #include "LPC17xx.h" +#include enum iicctrlvals { @@ -45,19 +47,20 @@ struct lpc17XXi2cRegs unsigned long I2CONCLR; }; -typedef volatile struct lpc17XXi2cRegs i2cDev; +typedef volatile struct lpc17XXi2cRegs* _i2cDev; +typedef UHANDLE i2cDev; -extern i2ctrl i2cwrite(i2cDev* dev,char address,char*data,int* cnt); -extern i2ctrl i2cwrite2(i2cDev* dev,char address,char*cmd,int* cmdcnt,char*data,int* datcnt); -extern i2ctrl i2cread(i2cDev* dev,char address,char*data,int* cnt); -extern i2cDev* i2copen(int count); -extern void i2cenable(i2cDev* dev); -extern void i2cdisable(i2cDev* dev); -extern void i2csetup(i2cDev* dev,int clkH,int clkL); -extern unsigned char i2cgetpclkfactor(i2cDev* dev); -extern void i2csetpclkfactor(i2cDev* dev,unsigned char pclkfactor); -extern void i2csetdatarate(i2cDev* dev,unsigned int dataRate); -extern int i2cgetdatarate(i2cDev* dev); +extern i2ctrl i2cwrite(i2cDev dev,char address,char*data,int* cnt); +extern i2ctrl i2cwrite2(i2cDev dev,char address,char*cmd,int* cmdcnt,char*data,int* datcnt); +extern i2ctrl i2cread(i2cDev dev,char address,char*data,int* cnt); +extern i2cDev i2copen(int count); +extern void i2cenable(i2cDev dev); +extern void i2cdisable(i2cDev dev); +extern void i2csetup(i2cDev dev,int clkH,int clkL); +extern unsigned char i2cgetpclkfactor(i2cDev dev); +extern void i2csetpclkfactor(i2cDev dev,unsigned char pclkfactor); +extern void i2csetdatarate(i2cDev dev,unsigned int dataRate); +extern int i2cgetdatarate(i2cDev dev); #endif diff --git a/lib/src/lpc17XX/IIC/iic.pro b/lib/src/lpc17XX/IIC/iic.pro --- a/lib/src/lpc17XX/IIC/iic.pro +++ b/lib/src/lpc17XX/IIC/iic.pro @@ -4,7 +4,7 @@ TARGET = libiic TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_IIC) HEADERSINSTALLPATH = $(LIBUC_INC_DIR_IIC) -LIBS += CORE +LIBS += CORE UHANDLE SOURCES += iic.c diff --git a/lib/src/lpc17XX/SSP/Makefile b/lib/src/lpc17XX/SSP/Makefile --- a/lib/src/lpc17XX/SSP/Makefile +++ b/lib/src/lpc17XX/SSP/Makefile @@ -5,12 +5,15 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_INC_DIR_SSP) HEADERS += ssp.h LIBSOURCES += ssp.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc17XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc TARGET=libssp -LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) -LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) +LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_SSP) HEADERSINSTALLPATH=$(LIBUC_INC_DIR_SSP) BSP=generic @@ -18,3 +21,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/lpc17XX/SSP/ssp.c b/lib/src/lpc17XX/SSP/ssp.c --- a/lib/src/lpc17XX/SSP/ssp.c +++ b/lib/src/lpc17XX/SSP/ssp.c @@ -23,99 +23,99 @@ #include "core.h" -void sspputw(sspDev* dev,int c) { +void sspputw(sspDev dev,int c) { volatile int a; - dev->SSPDataReg = c; - while (((dev->SSPStatReg & (1<<4)))); - a=dev->SSPDataReg; + ((_sspDev)dev)->SSPDataReg = c; + while (((((_sspDev)dev)->SSPStatReg & (1<<4)))); + a=((_sspDev)dev)->SSPDataReg; } -void sspputc(sspDev* dev,char c) { +void sspputc(sspDev dev,char c) { volatile char a; - dev->SSPDataReg = c; - while (((dev->SSPStatReg & (1<<4)))); - a=dev->SSPDataReg; + ((_sspDev)dev)->SSPDataReg = c; + while (((((_sspDev)dev)->SSPStatReg & (1<<4)))); + a=((_sspDev)dev)->SSPDataReg; } -void sspputnc(sspDev* dev,const char *c,unsigned int n) +void sspputnc(sspDev dev,const char *c,unsigned int n) { volatile char a; while(n--) { - dev->SSPDataReg = *c++; - while (((dev->SSPStatReg & (1<<4)))); - a=dev->SSPDataReg; + ((_sspDev)dev)->SSPDataReg = *c++; + while (((((_sspDev)dev)->SSPStatReg & (1<<4)))); + a=((_sspDev)dev)->SSPDataReg; } } -char sspgetc(sspDev* dev) { - dev->SSPDataReg = 0xffff; - while ((dev->SSPStatReg & (0x10))); - return ((char)dev->SSPDataReg); +char sspgetc(sspDev dev) { + ((_sspDev)dev)->SSPDataReg = 0xffff; + while ((((_sspDev)dev)->SSPStatReg & (0x10))); + return ((char)((_sspDev)dev)->SSPDataReg); } -void sspgetnc(sspDev* dev,char *c,unsigned int n) +void sspgetnc(sspDev dev,char *c,unsigned int n) { volatile char a; - while (((dev->SSPStatReg & (1<<2)))) a=dev->SSPDataReg; + while (((((_sspDev)dev)->SSPStatReg & (1<<2)))) a=((_sspDev)dev)->SSPDataReg; while(n) { - dev->SSPDataReg = 0xff; - while (((dev->SSPStatReg & (1<<4)))); - *c= (char)dev->SSPDataReg; + ((_sspDev)dev)->SSPDataReg = 0xff; + while (((((_sspDev)dev)->SSPStatReg & (1<<4)))); + *c= (char)((_sspDev)dev)->SSPDataReg; c++; n--; } } -int sspgetw(sspDev* dev) { +int sspgetw(sspDev dev) { int dummy; - while(((dev->SSPStatReg & (1<<2)))) - dummy = dev->SSPDataReg; - dev->SSPDataReg = 0xFFFF; - while (((dev->SSPStatReg & (1<<4)))); - return (dev->SSPDataReg); + while(((((_sspDev)dev)->SSPStatReg & (1<<2)))) + dummy = ((_sspDev)dev)->SSPDataReg; + ((_sspDev)dev)->SSPDataReg = 0xFFFF; + while (((((_sspDev)dev)->SSPStatReg & (1<<4)))); + return (((_sspDev)dev)->SSPDataReg); } -void sspputs(sspDev* dev,char *s) { +void sspputs(sspDev dev,char *s) { while (*s) sspputc(dev,*s++); } -void sspgets(sspDev* dev,char *s) { +void sspgets(sspDev dev,char *s) { while (*s && (*s!=0xd)) *s++ = sspgetc(dev); } -void sspsetup(sspDev* dev,unsigned char bitscount,int sspCtrlRegValue0,int sspCtrlRegValue1, unsigned int dataRate) +void sspsetup(sspDev dev,unsigned char bitscount,int sspCtrlRegValue0,int sspCtrlRegValue1, unsigned int dataRate) { - dev->SSPCtrlReg0 = sspCtrlRegValue0; - dev->SSPCtrlReg1 = sspCtrlRegValue1; + ((_sspDev)dev)->SSPCtrlReg0 = sspCtrlRegValue0; + ((_sspDev)dev)->SSPCtrlReg1 = sspCtrlRegValue1; sspsetupTRsize(dev,bitscount); sspsetdatarate(dev,dataRate); } -void sspsetupTRsize(sspDev* dev,unsigned char value) +void sspsetupTRsize(sspDev dev,unsigned char value) { disableSSP(dev); if(value < 4)value =4; value--; - dev->SSPCtrlReg0 |= value; - dev->SSPCtrlReg0 &= 0xFFFFFFF0 | value; + ((_sspDev)dev)->SSPCtrlReg0 |= value; + ((_sspDev)dev)->SSPCtrlReg0 &= 0xFFFFFFF0 | value; enableSSP(dev); } -void enableSSP(sspDev* dev) +void enableSSP(sspDev dev) { - dev->SSPCtrlReg1 |= 1<<1; + ((_sspDev)dev)->SSPCtrlReg1 |= 1<<1; } -void disableSSP(sspDev* dev) +void disableSSP(sspDev dev) { - dev->SSPCtrlReg1 &= -1 - (1<<1); + ((_sspDev)dev)->SSPCtrlReg1 &= -1 - (1<<1); } -void ssppowerup(sspDev* dev) +void ssppowerup(sspDev dev) { switch((int)dev) { @@ -130,7 +130,7 @@ void ssppowerup(sspDev* dev) } } -void ssppowerdown(sspDev* dev) +void ssppowerdown(sspDev dev) { switch((int)dev) { @@ -146,18 +146,18 @@ void ssppowerdown(sspDev* dev) } -sspDev* sspopen(int count){ - sspDev* dev; +sspDev sspopen(int count){ + sspDev dev; switch(count) { case 0: - dev = (sspDev*)((unsigned long)LPC_SSP0_BASE); + dev = (sspDev)((unsigned long)LPC_SSP0_BASE); break; case 1: - dev = (sspDev*)((unsigned long)LPC_SSP1_BASE); + dev = (sspDev)((unsigned long)LPC_SSP1_BASE); break; default: - dev = (sspDev*)0; + dev = (sspDev)0; break; } return dev; @@ -170,7 +170,7 @@ sspDev* sspopen(int count){ -unsigned char sspgetpclkfactor(sspDev* dev) +unsigned char sspgetpclkfactor(sspDev dev) { unsigned int clksel=0; const char clkselDec[]={4,1,2,8}; @@ -189,7 +189,7 @@ unsigned char sspgetpclkfactor(sspDev* d } -void sspsetpclkfactor(sspDev* dev,unsigned char pclkfactor) +void sspsetpclkfactor(sspDev dev,unsigned char pclkfactor) { const char clkselDec[]={1,1,2,2,0,0,0,0,3}; unsigned int clksel=0; @@ -212,7 +212,7 @@ void sspsetpclkfactor(sspDev* dev,unsign -void sspsetdatarate(sspDev* dev,unsigned int dataRate) +void sspsetdatarate(sspDev dev,unsigned int dataRate) { unsigned int pclk = 0; unsigned int cpuclk=0; @@ -234,7 +234,38 @@ void sspsetdatarate(sspDev* dev,unsigned if(sspsclkl<2) sspsclkl = 2; } sspsclkl &= 0xFE; - dev->SSPClkPrescReg = sspsclkl; + ((_sspDev)dev)->SSPClkPrescReg = sspsclkl; +} + + + +unsigned int sspgetdatarate(sspDev dev) +{ + unsigned int dataRate; + unsigned int pclk = 0; + unsigned int cpuclk=0; + if(dev==0)return; + cpuclk = coregetCpuFreq(); + pclk = (cpuclk) / sspgetpclkfactor(dev); + dataRate = pclk/((_sspDev)dev)->SSPClkPrescReg; + return dataRate; } + + + + + + + + + + + + + + + + + diff --git a/lib/src/lpc17XX/SSP/ssp.h b/lib/src/lpc17XX/SSP/ssp.h --- a/lib/src/lpc17XX/SSP/ssp.h +++ b/lib/src/lpc17XX/SSP/ssp.h @@ -19,10 +19,13 @@ -- Author : Alexis Jeandet -- Mail : alexis.jeandet@gmail.com -------------------------------------------------------------------------------*/ -#include "LPC17xx.h" #ifndef SSP_H #define SSP_H +#include "LPC17xx.h" +#include + + #define l4bits ((1<<1)+(1)) //0011 4 bit transfer #define l5bits ((1<<2)) //0100 5 bit transfer #define l6bits ((1<<2)+(1)) //0101 6 bit transfer @@ -57,7 +60,7 @@ #define SLAVEOUTPUTDISABLEMODE (1<<3) -#define sspisslave(dev) ((((dev)->SSPCtrlReg1>>2) & 1)==1) +#define sspisslave(dev) ((((((_sspDev)dev))->SSPCtrlReg1>>2) & 1)==1) struct sspRegs { @@ -73,24 +76,34 @@ struct sspRegs unsigned long SSPDMACtrlReg; }; -typedef volatile struct sspRegs sspDev; +typedef volatile struct sspRegs* _sspDev; +typedef UHANDLE sspDev; -extern sspDev* sspopen(int count); -extern void sspputc(sspDev* dev,char c); -extern void sspputnc(sspDev* dev,const char *c,unsigned int n); -extern void sspputw(sspDev* dev,int c); -extern void sspputs(sspDev* dev,char *s); -extern void sspgets(sspDev* dev,char *s); -extern char sspgetc(sspDev* dev); -extern void sspgetnc(sspDev* dev,char *c,unsigned int n); -extern int sspgetw(sspDev* dev); -extern void enableSSP(sspDev* dev); -extern void disableSSP(sspDev* dev); -extern void sspsetup(sspDev* dev,unsigned char bitscount,int sspCtrlRegValue0,int sspCtrlRegValue1, unsigned int dataRate); -extern void sspsetupTRsize(sspDev* dev,unsigned char value); -extern unsigned char sspgetpclkfactor(sspDev* dev); -extern void sspsetpclkfactor(sspDev* dev,unsigned char pclkfactor); -extern void sspsetdatarate(sspDev* dev,unsigned int dataRate); +extern sspDev sspopen(int count); +extern void sspputc(sspDev dev,char c); +extern void sspputnc(sspDev dev,const char *c,unsigned int n); +extern void sspputw(sspDev dev,int c); +extern void sspputs(sspDev dev,char *s); +extern void sspgets(sspDev dev,char *s); +extern char sspgetc(sspDev dev); +extern void sspgetnc(sspDev dev,char *c,unsigned int n); +extern int sspgetw(sspDev dev); +extern void enableSSP(sspDev dev); +extern void disableSSP(sspDev dev); +extern void sspsetup(sspDev dev,unsigned char bitscount,int sspCtrlRegValue0,int sspCtrlRegValue1, unsigned int dataRate); +extern void sspsetupTRsize(sspDev dev,unsigned char value); +extern unsigned char sspgetpclkfactor(sspDev dev); +extern void sspsetpclkfactor(sspDev dev,unsigned char pclkfactor); +extern void sspsetdatarate(sspDev dev,unsigned int dataRate); +extern unsigned int sspgetdatarate(sspDev dev); #endif + + + + + + + + diff --git a/lib/src/lpc17XX/SSP/ssp.pro b/lib/src/lpc17XX/SSP/ssp.pro --- a/lib/src/lpc17XX/SSP/ssp.pro +++ b/lib/src/lpc17XX/SSP/ssp.pro @@ -4,7 +4,7 @@ TARGET = libssp TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_SSP) HEADERSINSTALLPATH = $(LIBUC_INC_DIR_SSP) -LIBS += CORE +LIBS += CORE UHANDLE SOURCES += ssp.c diff --git a/lib/src/lpc17XX/UART/Makefile b/lib/src/lpc17XX/UART/Makefile --- a/lib/src/lpc17XX/UART/Makefile +++ b/lib/src/lpc17XX/UART/Makefile @@ -5,12 +5,15 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_INC_DIR)/UART HEADERS += uart.h LIBSOURCES += uart.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc17XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc17XX-arm-noabi-gcc TARGET=libuart -LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) -LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) +LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) TARGETINSTALLPATH=$(LIBUC_LIBS_DIR)/UART HEADERSINSTALLPATH=$(LIBUC_INC_DIR)/UART BSP=generic @@ -18,3 +21,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/lpc17XX/UART/uart.c b/lib/src/lpc17XX/UART/uart.c --- a/lib/src/lpc17XX/UART/uart.c +++ b/lib/src/lpc17XX/UART/uart.c @@ -23,23 +23,23 @@ #include "uart.h" -void uartputc(uartDev* dev,char c) { - while (!((dev->LineStat & (1<<5)))); - dev->RWreg = c; +void uartputc(uartDev dev,char c) { + while (!((((_uartDev)dev)->LineStat & (1<<5)))); + ((_uartDev)dev)->RWreg = c; } -char uartgetc(uartDev* dev) { - while (!((dev->LineStat & 1))); - return (char)dev->RWreg; +char uartgetc(uartDev dev) { + while (!((((_uartDev)dev)->LineStat & 1))); + return (char)((_uartDev)dev)->RWreg; } -void uartputs(uartDev* dev,char *s) { +void uartputs(uartDev dev,char *s) { while (*s) uartputc(dev,*s++); } -void uartgets(uartDev* dev,char *s) { +void uartgets(uartDev dev,char *s) { while (*s && (*s!=0xd)) *s++ = uartgetc(dev); } @@ -87,16 +87,16 @@ void uarton(int count) -void uartsetup(uartDev* dev,unsigned int baudRate,unsigned char WordLength,unsigned char StopBitCnt,unsigned char Parity) +void uartsetup(uartDev dev,unsigned int baudRate,unsigned char WordLength,unsigned char StopBitCnt,unsigned char Parity) { if(WordLength>9)WordLength=8; if((StopBitCnt>2)||(StopBitCnt==0))StopBitCnt=1; if(Parity>7)Parity=0; - dev->LineCtrl = (WordLength-5) + ((StopBitCnt-1)<<2) + (Parity<<3); + ((_uartDev)dev)->LineCtrl = (WordLength-5) + ((StopBitCnt-1)<<2) + (Parity<<3); uartsetbaudrate(dev,baudRate); } -unsigned char uartgetpclkfactor(uartDev* dev) +unsigned char uartgetpclkfactor(uartDev dev) { unsigned int clksel=0; const char clkselDec[]={4,1,2,8}; @@ -120,7 +120,7 @@ unsigned char uartgetpclkfactor(uartDev* return clkselDec[clksel]; } -void uartsetpclkfactor(uartDev* dev,unsigned char pclkfactor) +void uartsetpclkfactor(uartDev dev,unsigned char pclkfactor) { const char clkselDec[]={1,1,2,2,0,0,0,0,3}; unsigned int clksel=0; @@ -147,7 +147,7 @@ void uartsetpclkfactor(uartDev* dev,unsi } } -void uartsetbaudrate(uartDev* dev,unsigned int baudRate) +void uartsetbaudrate(uartDev dev,unsigned int baudRate) { unsigned int pclk = 0; unsigned int clksel=0; @@ -162,29 +162,29 @@ void uartsetbaudrate(uartDev* dev,unsign uartsetpclkfactor(dev,pclkfact/2); pclk = cpuclk / uartgetpclkfactor(dev); } - dev->LineCtrl |= 128; - dev->RWreg = pclk/(baudRate*16); - dev->LineCtrl &= ~(128); + ((_uartDev)dev)->LineCtrl |= 128; + ((_uartDev)dev)->RWreg = pclk/(baudRate*16); + ((_uartDev)dev)->LineCtrl &= ~(128); } -uartDev* uartopen(int count){ - uartDev* dev; +uartDev uartopen(int count){ + uartDev dev; switch(count) { case 0: - dev = (uartDev*)((unsigned long)LPC_UART0_BASE); + dev = (uartDev)((unsigned long)LPC_UART0_BASE); break; case 1: - dev = (uartDev*)((unsigned long)LPC_UART1_BASE); + dev = (uartDev)((unsigned long)LPC_UART1_BASE); break; case 2: - dev = (uartDev*)((unsigned long)LPC_UART2_BASE); + dev = (uartDev)((unsigned long)LPC_UART2_BASE); break; case 3: - dev = (uartDev*)((unsigned long)LPC_UART3_BASE); + dev = (uartDev)((unsigned long)LPC_UART3_BASE); break; default: - dev = (uartDev*)0; + dev = (uartDev)0; break; } return dev; diff --git a/lib/src/lpc17XX/UART/uart.h b/lib/src/lpc17XX/UART/uart.h --- a/lib/src/lpc17XX/UART/uart.h +++ b/lib/src/lpc17XX/UART/uart.h @@ -21,7 +21,9 @@ -------------------------------------------------------------------------------*/ #ifndef UART_H #define UART_H + #include "LPC17xx.h" +#include #define uartNoParity 0 @@ -41,19 +43,20 @@ struct LPC17XXuartRegs unsigned long ScratchPad; }; -typedef volatile struct LPC17XXuartRegs uartDev; +typedef volatile struct LPC17XXuartRegs* _uartDev; +typedef UHANDLE uartDev; -extern uartDev* uartopen(int count); +extern uartDev uartopen(int count); extern void uarton(int count); extern void uartoff(int count); -extern void uartputc(uartDev* dev,char c); -extern void uartputs(uartDev* dev,char *s); -extern void uartgets(uartDev* dev,char *s); -extern char uartgetc(uartDev* dev); -extern void uartsetbaudrate(uartDev* dev,unsigned int baudRate); -extern unsigned char uartgetpclkfactor(uartDev* dev); -extern void uartsetpclkfactor(uartDev* dev,unsigned char pclkfactor); -extern void uartsetup(uartDev* dev,unsigned int baudRate,unsigned char WordLength,unsigned char StopBitCnt,unsigned char Parity); +extern void uartputc(uartDev dev,char c); +extern void uartputs(uartDev dev,char *s); +extern void uartgets(uartDev dev,char *s); +extern char uartgetc(uartDev dev); +extern void uartsetbaudrate(uartDev dev,unsigned int baudRate); +extern unsigned char uartgetpclkfactor(uartDev dev); +extern void uartsetpclkfactor(uartDev dev,unsigned char pclkfactor); +extern void uartsetup(uartDev dev,unsigned int baudRate,unsigned char WordLength,unsigned char StopBitCnt,unsigned char Parity); #endif diff --git a/lib/src/lpc17XX/UART/uart.pro b/lib/src/lpc17XX/UART/uart.pro --- a/lib/src/lpc17XX/UART/uart.pro +++ b/lib/src/lpc17XX/UART/uart.pro @@ -4,7 +4,7 @@ TARGET = libuart TARGETINSTALLPATH = $(LIBUC_LIBS_DIR)/UART HEADERSINSTALLPATH = $(LIBUC_INC_DIR)/UART -LIBS += CORE +LIBS += CORE UHANDLE SOURCES += uart.c diff --git a/lib/src/lpc21XX/CORE/Makefile b/lib/src/lpc21XX/CORE/Makefile --- a/lib/src/lpc21XX/CORE/Makefile +++ b/lib/src/lpc21XX/CORE/Makefile @@ -5,7 +5,10 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_INC_DIR)/CORE HEADERS += core.h LIBSOURCES += core.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc21XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc TARGET=libcore @@ -18,3 +21,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/lpc21XX/IIC/Makefile b/lib/src/lpc21XX/IIC/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/IIC/Makefile @@ -0,0 +1,30 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_IIC) +HEADERS += iic.h +LIBSOURCES += iic.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libiic +LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_IIC) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_IIC) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/lpc21XX/IIC/iic.c b/lib/src/lpc21XX/IIC/iic.c new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/IIC/iic.c @@ -0,0 +1,350 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#include "iic.h" +#include "core.h" + +#define iicputdata(iicdev,W,IICONSET,IICONCLR) {((_i2cDev)(iicdev))->I2DAT = (W);\ + ((_i2cDev)(iicdev))->I2CONSET = (IICONSET);\ + ((_i2cDev)(iicdev))->I2CONCLR = (IICONCLR);} + +#define iicgetdata(iicdev,W,IICONSET,IICONCLR) {(W) = ((_i2cDev)(iicdev))->I2DAT;\ + ((_i2cDev)(iicdev))->I2CONSET = (IICONSET);\ + ((_i2cDev)(iicdev))->I2CONCLR = (IICONCLR);} + +i2ctrl i2cwrite2(i2cDev dev,char address,char*cmd,int* cmdcnt,char*data,int* datcnt) +{ + char iicdat=0; + ((_i2cDev)dev)->I2CONCLR = 0x28; + iicdat = (address<<1) & 0xFE; + int count = (*datcnt) + 2; + (*datcnt) = 0; + while(((_i2cDev)dev)->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout + ((_i2cDev)dev)->I2CONSET = (1<<5); //initiate transfert + while(count>0) + { + while((((_i2cDev)dev)->I2CONSET & 0x08)!=0x08); + switch(((_i2cDev)dev)->I2STAT) + { + case 0x08: + iicputdata(dev,iicdat,(1<<2),0x28); + iicdat = *cmd++; + break; + case 0x10: + iicputdata(dev,iicdat,(1<<2),0x28); + iicdat = *cmd++; + *cmdcnt = (*cmdcnt) - 1; + break; + case 0x18: + iicputdata(dev,iicdat,0,0x08); + if((*cmdcnt)>1) + { + iicdat = *cmd++; + *cmdcnt = (*cmdcnt) - 1; + } + else + { + count--; + iicdat = *data++; + } + break; + case 0x28: + iicputdata(dev,iicdat,(1<<2),0x08); + if((*cmdcnt)>1) + { + iicdat = *cmd++; + *cmdcnt = (*cmdcnt) - 1; + } + else + { + count--; + *datcnt = (*datcnt)+1; + iicdat = *data++; + } + break; + case 0x20: + return i2noack; + count = 0; + break; + case 0x30: + return i2noack; + count = 0; + break; + case 0x38: + return i2arbloss; + count = 0; + break; + default: + break; + } + + } + ((_i2cDev)dev)->I2CONSET = (1<<4) + (1<<2); + ((_i2cDev)dev)->I2CONCLR = 1<<3; + return i2noerr; +} + + + +i2ctrl i2cwrite(i2cDev dev,char address,char*data,int* cnt) +{ + char iicdat=0; + ((_i2cDev)dev)->I2CONCLR = 0x28; + iicdat = (address<<1) & 0xFE; + int count = (*cnt) + 1; + *cnt = 0; + while(((_i2cDev)dev)->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout + ((_i2cDev)dev)->I2CONSET = (1<<5); //initiate transfert + while(count>0) + { + while((((_i2cDev)dev)->I2CONSET & 0x08)!=0x08); + switch(((_i2cDev)dev)->I2STAT) + { + case 0x08: + iicputdata(dev,iicdat,(1<<2),0x28); + iicdat = *data++; + break; + case 0x10: + iicputdata(dev,iicdat,(1<<2),0x28); + iicdat = *data++; + break; + case 0x18: + iicputdata(dev,iicdat,0,0x08); + count--; + iicdat = *data++; + break; + case 0x28: + iicputdata(dev,iicdat,(1<<2),0x08); + *cnt = (*cnt)+1; + count--; + iicdat = *data++; + break; + case 0x20: + return i2noack; + count = 0; + break; + case 0x30: + return i2noack; + count = 0; + break; + case 0x38: + return i2arbloss; + count = 0; + break; + default: + break; + } + + } + ((_i2cDev)dev)->I2CONSET = (1<<4) + (1<<2); + ((_i2cDev)dev)->I2CONCLR = 1<<3; + return i2noerr; +} + + +i2ctrl i2cread(i2cDev dev,char address,char*data,int* cnt) +{ + char iicdat=0; + ((_i2cDev)dev)->I2CONCLR = 0x28; + iicdat = (address<<1) + 1; + unsigned int count = (*cnt); + *cnt = 0; + while(((_i2cDev)dev)->I2STAT != 0xF8); //waiting for device to be ready /!\ should add timeout + ((_i2cDev)dev)->I2CONSET = (1<<5); //initiate transfert + while(count!=0) + { + while((((_i2cDev)dev)->I2CONSET & 0x08)!=0x08); + switch(((_i2cDev)dev)->I2STAT) + { + while((((_i2cDev)dev)->I2CONSET & (1<<3))!=(1<<3)); + case 0x08: + iicputdata(dev,iicdat,(1<<2),0x28); + break; + case 0x10: + iicputdata(dev,iicdat,(1<<2),0x28); + break; + case 0x40: + if((count!=1)) ((_i2cDev)dev)->I2CONSET = (1<<2); + else ((_i2cDev)dev)->I2CONCLR = (1<<2); + ((_i2cDev)dev)->I2CONCLR = 1<<3; + break; + case 0x50: + if((count==2)) iicgetdata(dev,iicdat,(0),(0x0c)) + else iicgetdata(dev,iicdat,(4),(8)) + count--; + *cnt = (*cnt) + 1; + *data = iicdat; + data++; + break; + case 0x48: + ((_i2cDev)dev)->I2CONSET = 0x14; + ((_i2cDev)dev)->I2CONCLR = 8; + return i2noerr; + break; + case 0x58: + iicgetdata(dev,iicdat,(0x14),(8)); + count--; + *cnt = (*cnt) + 1; + *data = iicdat; + data++; + return i2noerr; + break; + default: + break; + } + + } + ((_i2cDev)dev)->I2CONSET = (1<<4); + ((_i2cDev)dev)->I2CONCLR =(1<<2); + ((_i2cDev)dev)->I2CONCLR = 1<<3; + return i2noerr; +} + + +void i2csetup(i2cDev dev,int clkH,int clkL) +{ + ((_i2cDev)dev)->I2CONCLR = 0x6C; + ((_i2cDev)dev)->I2SCLH = clkH; + ((_i2cDev)dev)->I2SCLL = clkL; + ((_i2cDev)dev)->I2CONSET = 1<<6; //enable I2C block + ((_i2cDev)dev)->I2CONCLR = 0x28; +} + + +void i2cenable(i2cDev dev) +{ + ((_i2cDev)dev)->I2CONSET = 1<<6; +} + + +void i2cdisable(i2cDev dev) +{ + ((_i2cDev)dev)->I2CONCLR = (1<<6); +} + + +i2cDev i2copen(int count){ + i2cDev dev; + switch(count) + { + case 0: + dev = (i2cDev)((unsigned long)I2C0_BASE_ADDR); + break; + case 1: + dev = (i2cDev)((unsigned long)I2C1_BASE_ADDR); + break; + case 2: + dev = (i2cDev)((unsigned long)I2C2_BASE_ADDR); + break; + default: + dev = (i2cDev)0; + break; + } + return dev; +} + + + +unsigned char i2cgetpclkfactor(i2cDev dev) +{ + unsigned int clksel=0; + const char clkselDec[]={4,1,2,8}; + switch((int)dev) + { + case (int)I2C0_BASE_ADDR: + clksel = (PCLKSEL0>>14) & 3; + break; + case (int)I2C1_BASE_ADDR: + clksel = (PCLKSEL1>>6) & 3; + break; + case (int)I2C2_BASE_ADDR: + clksel = (PCLKSEL1>>20) & 3; + break; + default: + break; + } + return clkselDec[clksel]; +} + + +void i2csetpclkfactor(i2cDev dev,unsigned char pclkfactor) +{ + const char clkselDec[]={1,1,2,2,0,0,0,0,3}; + unsigned int clksel=0; + switch((int)dev) + { + case (int)I2C0_BASE_ADDR: + PCLKSEL0 |= clkselDec[pclkfactor]<<14; + PCLKSEL0 &= clkselDec[pclkfactor]<<14; + break; + case (int)I2C1_BASE_ADDR: + PCLKSEL1 |= clkselDec[pclkfactor]<<6; + PCLKSEL1 &= clkselDec[pclkfactor]<<6; + break; + case (int)I2C2_BASE_ADDR: + PCLKSEL1 |= clkselDec[pclkfactor]<<20; + PCLKSEL1 &= clkselDec[pclkfactor]<<20; + break; + default: + break; + } + +} + + +void i2csetdatarate(i2cDev dev,unsigned int dataRate) +{ + unsigned int pclk = 0; + unsigned int cpuclk=0; + unsigned int i2csclkl=0; + if(dev==0)return; + cpuclk = coregetCpuFreq(); + pclk = cpuclk / i2cgetpclkfactor(dev); + i2csclkl = (pclk / dataRate)>>1; + if(i2csclkl<4) i2csclkl = 4; + i2csetup(dev,i2csclkl,i2csclkl); +} + +int i2cgetdatarate(i2cDev dev) +{ + unsigned int dataRate=0; + unsigned int pclk = 0; + unsigned int cpuclk=0; + unsigned int i2csclkl=0; + if(dev==0)return 0; + cpuclk = coregetCpuFreq(); + pclk = cpuclk / i2cgetpclkfactor(dev); + dataRate = pclk /( ((_i2cDev)dev)->I2SCLH + ((_i2cDev)dev)->I2SCLL); + return dataRate; +} + + + + + + + + + + + + + diff --git a/lib/src/lpc21XX/IIC/iic.h b/lib/src/lpc21XX/IIC/iic.h new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/IIC/iic.h @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef IIC_H +#define IIC_H + +#include "LPC23xx.h" +#include + +enum iicctrlvals +{ + i2noerr, + i2noack, + i2arbloss, + i2busy, + i2timeout +}; + +typedef enum iicctrlvals i2ctrl; + +struct lpc17XXi2cRegs +{ + unsigned long I2CONSET; + unsigned long I2STAT; + unsigned long I2DAT; + unsigned long I2ADR; + unsigned long I2SCLH; + unsigned long I2SCLL; + unsigned long I2CONCLR; +}; + +typedef volatile struct lpc17XXi2cRegs* _i2cDev; +typedef UHANDLE i2cDev; + +extern i2ctrl i2cwrite(i2cDev dev,char address,char*data,int* cnt); +extern i2ctrl i2cwrite2(i2cDev dev,char address,char*cmd,int* cmdcnt,char*data,int* datcnt); +extern i2ctrl i2cread(i2cDev dev,char address,char*data,int* cnt); +extern i2cDev i2copen(int count); +extern void i2cenable(i2cDev dev); +extern void i2cdisable(i2cDev dev); +extern void i2csetup(i2cDev dev,int clkH,int clkL); +extern unsigned char i2cgetpclkfactor(i2cDev dev); +extern void i2csetpclkfactor(i2cDev dev,unsigned char pclkfactor); +extern void i2csetdatarate(i2cDev dev,unsigned int dataRate); +extern int i2cgetdatarate(i2cDev dev); +#endif + + + + + + + + + diff --git a/lib/src/lpc21XX/IIC/iic.pro b/lib/src/lpc21XX/IIC/iic.pro new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/IIC/iic.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +ARCH = lpc21XX-arm-noabi-gcc +TARGET = libiic +TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_IIC) +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_IIC) + +LIBS += CORE UHANDLE + +SOURCES += iic.c + + +HEADERS += iic.h diff --git a/lib/src/lpc21XX/Makefile b/lib/src/lpc21XX/Makefile --- a/lib/src/lpc21XX/Makefile +++ b/lib/src/lpc21XX/Makefile @@ -6,10 +6,14 @@ include $(LIBUC)/rules/common/rules.mk all:subdir make -C CORE make -C UART + make -C IIC + make -C SSP @echo Code compiled clean: make clean -C CORE make clean -C UART + make clean -C IIC + make clean -C SSP @echo Code compiled diff --git a/lib/src/lpc21XX/SSP/Makefile b/lib/src/lpc21XX/SSP/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/SSP/Makefile @@ -0,0 +1,30 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_SSP) +HEADERS += ssp.h +LIBSOURCES += ssp.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libssp +LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR_SSP) +HEADERSINSTALLPATH=$(LIBUC_INC_DIR_SSP) +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/lpc21XX/SSP/ssp.c b/lib/src/lpc21XX/SSP/ssp.c new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/SSP/ssp.c @@ -0,0 +1,240 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#include "ssp.h" +#include "core.h" + + +void sspputw(sspDev dev,int c) { + volatile int a; + ((_sspDev)dev)->SSPDataReg = c; + while (((((_sspDev)dev)->SSPStatReg & (1<<4)))); + a=((_sspDev)dev)->SSPDataReg; +} + +void sspputc(sspDev dev,char c) { + volatile char a; + ((_sspDev)dev)->SSPDataReg = c; + while (((((_sspDev)dev)->SSPStatReg & (1<<4)))); + a=((_sspDev)dev)->SSPDataReg; +} + +void sspputnc(sspDev dev,const char *c,unsigned int n) +{ + volatile char a; + while(n--) + { + ((_sspDev)dev)->SSPDataReg = *c++; + while (((((_sspDev)dev)->SSPStatReg & (1<<4)))); + a=((_sspDev)dev)->SSPDataReg; + } +} + +char sspgetc(sspDev dev) { + ((_sspDev)dev)->SSPDataReg = 0xffff; + while ((((_sspDev)dev)->SSPStatReg & (0x10))); + return ((char)((_sspDev)dev)->SSPDataReg); +} + +void sspgetnc(sspDev dev,char *c,unsigned int n) +{ + volatile char a; + while (((((_sspDev)dev)->SSPStatReg & (1<<2)))) a=((_sspDev)dev)->SSPDataReg; + while(n) + { + ((_sspDev)dev)->SSPDataReg = 0xff; + while (((((_sspDev)dev)->SSPStatReg & (1<<4)))); + *c= (char)((_sspDev)dev)->SSPDataReg; + c++; + n--; + } +} + +int sspgetw(sspDev dev) { + int dummy; + while(((((_sspDev)dev)->SSPStatReg & (1<<2)))) + dummy = ((_sspDev)dev)->SSPDataReg; + ((_sspDev)dev)->SSPDataReg = 0xFFFF; + while (((((_sspDev)dev)->SSPStatReg & (1<<4)))); + return (((_sspDev)dev)->SSPDataReg); +} + + +void sspputs(sspDev dev,char *s) { + while (*s) sspputc(dev,*s++); +} + + +void sspgets(sspDev dev,char *s) { + while (*s && (*s!=0xd)) *s++ = sspgetc(dev); +} + +void sspsetup(sspDev dev,unsigned char bitscount,int sspCtrlRegValue0,int sspCtrlRegValue1, unsigned int dataRate) +{ + ((_sspDev)dev)->SSPCtrlReg0 = sspCtrlRegValue0; + ((_sspDev)dev)->SSPCtrlReg1 = sspCtrlRegValue1; + sspsetupTRsize(dev,bitscount); + sspsetdatarate(dev,dataRate); +} + +void sspsetupTRsize(sspDev dev,unsigned char value) +{ + disableSSP(dev); + if(value < 4)value =4; + value--; + ((_sspDev)dev)->SSPCtrlReg0 |= value; + ((_sspDev)dev)->SSPCtrlReg0 &= 0xFFFFFFF0 | value; + enableSSP(dev); +} + +void enableSSP(sspDev dev) +{ + ((_sspDev)dev)->SSPCtrlReg1 |= 1<<1; +} + +void disableSSP(sspDev dev) +{ + ((_sspDev)dev)->SSPCtrlReg1 &= -1 - (1<<1); +} + +void ssppowerup(sspDev dev) +{ + switch((int)dev) + { + case (int)SSP0_BASE_ADDR: + PCONP |= ( 1 << 21 ); + break; + case (int)SSP1_BASE_ADDR: + PCONP |= ( 1 << 10 ); + break; + default: + break; + } +} + +void ssppowerdown(sspDev dev) +{ + switch((int)dev) + { + case (int)SSP0_BASE_ADDR: + PCONP &= ~( 1 << 21 ); + break; + case (int)SSP1_BASE_ADDR: + PCONP &= ~( 1 << 10 ); + break; + default: + break; + } +} + + +sspDev sspopen(int count){ + sspDev dev; + switch(count) + { + case 0: + dev = (sspDev)((unsigned long)SSP0_BASE_ADDR); + break; + case 1: + dev = (sspDev)((unsigned long)SSP1_BASE_ADDR); + break; + default: + dev = (sspDev)0; + break; + } + return dev; +} + + + + + + + + +unsigned char sspgetpclkfactor(sspDev dev) +{ + unsigned int clksel=0; + const char clkselDec[]={4,1,2,8}; + switch((int)dev) + { + case (int)SSP0_BASE_ADDR: + clksel = (PCLKSEL1>>10) & 3; + break; + case (int)SSP1_BASE_ADDR: + clksel = (PCLKSEL0>>20) & 3; + break; + default: + break; + } + return clkselDec[clksel]; +} + + +void sspsetpclkfactor(sspDev dev,unsigned char pclkfactor) +{ + const char clkselDec[]={1,1,2,2,0,0,0,0,3}; + unsigned int clksel=0; + switch((int)dev) + { + case (int)SSP0_BASE_ADDR: + PCLKSEL1 |= clkselDec[pclkfactor]<<10; + PCLKSEL1 &= clkselDec[pclkfactor]<<10; + break; + case (int)SSP1_BASE_ADDR: + PCLKSEL0 |= clkselDec[pclkfactor]<<20; + PCLKSEL0 &= clkselDec[pclkfactor]<<20; + break; + default: + break; + } + +} + + + + +void sspsetdatarate(sspDev dev,unsigned int dataRate) +{ + unsigned int pclk = 0; + unsigned int cpuclk=0; + unsigned int sspsclkl=0; + unsigned char error; + if(dev==0)return; + cpuclk = coregetCpuFreq(); + pclk = (cpuclk) / sspgetpclkfactor(dev); + sspsclkl = ((pclk*32) / (dataRate)); + error = (unsigned char)(sspsclkl & 0x3F); + if(error >= 0x1F) sspsclkl = sspsclkl + 0x1F; + sspsclkl = sspsclkl / 32; + if(sspisslave(dev)) + { + if(sspsclkl<12) sspsclkl = 12; + } + else + { + if(sspsclkl<2) sspsclkl = 2; + } + sspsclkl &= 0xFE; + ((_sspDev)dev)->SSPClkPrescReg = sspsclkl; +} + + diff --git a/lib/src/lpc21XX/SSP/ssp.h b/lib/src/lpc21XX/SSP/ssp.h new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/SSP/ssp.h @@ -0,0 +1,108 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef SSP_H +#define SSP_H + +#include "LPC23xx.h" +#include + + +#define l4bits ((1<<1)+(1)) //0011 4 bit transfer +#define l5bits ((1<<2)) //0100 5 bit transfer +#define l6bits ((1<<2)+(1)) //0101 6 bit transfer +#define l7bits ((1<<1)+(1<<1)) //0110 7 bit transfer +#define l8bits ((1<<2)+(1<<1)+(1)) //0111 8 bit transfer +#define l9bits ((1<<3)) //1000 9 bit transfer +#define l10bits ((1<<3)+(1)) //1001 10 bit transfer +#define l11bits ((1<<3)+(1<<1)) //1010 11 bit transfer +#define l12bits ((1<<3)+(1<<1)+1) //1011 12 bit transfer +#define l13bits ((1<<3)+(1<<2)) //1100 13 bit transfer +#define l14bits ((1<<3)+(1<<2)+1) //1101 14 bit transfer +#define l15bits ((1<<3)+(1<<2)+(1<<1)) //1110 15 bit transfer +#define l16bits ((1<<3)+(1<<2)+(1<<1)+1) //1111 16 bit transfer + +#define FFSPI 0 +#define FFTI (1<<4) +#define FFMICROWIRE (1<<5) + +#define CLKINHLOW 0 +#define CLKINHHIGH (1<<6) + +#define CKfirstEdge 0 +#define CKsecondEdge (1<<7) + + + +#define loopbackOFF 0 +#define loopbackON 1 + +#define MASTERMODE 0 +#define SLAVEMODE (1<<2) + +#define SLAVEOUTPUTDISABLEMODE (1<<3) + +#define sspisslave(dev) ((((((_sspDev)dev))->SSPCtrlReg1>>2) & 1)==1) + +struct sspRegs +{ + unsigned long SSPCtrlReg0; + unsigned long SSPCtrlReg1; + unsigned long SSPDataReg; + unsigned long SSPStatReg; + unsigned long SSPClkPrescReg; + unsigned long SSPIntMaskReg; + unsigned long SSPRawIntStatReg; + unsigned long SSPMaskedIntStatReg; + unsigned long SSPIntClearReg; + unsigned long SSPDMACtrlReg; +}; + +typedef volatile struct sspRegs* _sspDev; +typedef UHANDLE sspDev; + +extern sspDev sspopen(int count); +extern void sspputc(sspDev dev,char c); +extern void sspputnc(sspDev dev,const char *c,unsigned int n); +extern void sspputw(sspDev dev,int c); +extern void sspputs(sspDev dev,char *s); +extern void sspgets(sspDev dev,char *s); +extern char sspgetc(sspDev dev); +extern void sspgetnc(sspDev dev,char *c,unsigned int n); +extern int sspgetw(sspDev dev); +extern void enableSSP(sspDev dev); +extern void disableSSP(sspDev dev); +extern void sspsetup(sspDev dev,unsigned char bitscount,int sspCtrlRegValue0,int sspCtrlRegValue1, unsigned int dataRate); +extern void sspsetupTRsize(sspDev dev,unsigned char value); +extern unsigned char sspgetpclkfactor(sspDev dev); +extern void sspsetpclkfactor(sspDev dev,unsigned char pclkfactor); +extern void sspsetdatarate(sspDev dev,unsigned int dataRate); + +#endif + + + + + + + + + diff --git a/lib/src/lpc21XX/SSP/ssp.pro b/lib/src/lpc21XX/SSP/ssp.pro new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/SSP/ssp.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +ARCH = lpc21XX-arm-noabi-gcc +TARGET = libssp +TARGETINSTALLPATH = $(LIBUC_LIBS_DIR_SSP) +HEADERSINSTALLPATH = $(LIBUC_INC_DIR_SSP) + +LIBS += CORE UHANDLE + +SOURCES += ssp.c + + +HEADERS += ssp.h diff --git a/lib/src/lpc21XX/UART/Makefile b/lib/src/lpc21XX/UART/Makefile --- a/lib/src/lpc21XX/UART/Makefile +++ b/lib/src/lpc21XX/UART/Makefile @@ -5,12 +5,15 @@ LIBUC = /opt/libuc2 HEADERSINSTALLPATH = $(LIBUC_INC_DIR)/UART HEADERS += uart.h LIBSOURCES += uart.c +OBJDIR = obj +BINDIR = bin OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) ARCH = lpc21XX-arm-noabi-gcc ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc TARGET=libuart -LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) -LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) +LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) $(LIBUC_INC_DIR_UHANDLE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) $(LIBUC_LIBS_DIR_UHANDLE_CMD) $(LIBUC_LIBS_UHANDLE) TARGETINSTALLPATH=$(LIBUC_LIBS_DIR)/UART HEADERSINSTALLPATH=$(LIBUC_INC_DIR)/UART BSP=generic @@ -18,3 +21,10 @@ include $(ARCHFOLDER)/rules.mk all:lib @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h + rm -f $(DEVSOURCESND) + rm -f *.d diff --git a/lib/src/lpc21XX/UART/uart.c b/lib/src/lpc21XX/UART/uart.c --- a/lib/src/lpc21XX/UART/uart.c +++ b/lib/src/lpc21XX/UART/uart.c @@ -23,23 +23,23 @@ #include "uart.h" -void uartputc(uartDev* dev,char c) { - while (!((dev->LineStat & (1<<5)))); - dev->RWreg = c; +void uartputc(uartDev dev,char c) { + while (!((((_uartDev)dev)->LineStat & (1<<5)))); + ((_uartDev)dev)->RWreg = c; } -char uartgetc(uartDev* dev) { - while (!((dev->LineStat & 1))); - return (char)dev->RWreg; +char uartgetc(uartDev dev) { + while (!((((_uartDev)dev)->LineStat & 1))); + return (char)((_uartDev)dev)->RWreg; } -void uartputs(uartDev* dev,char *s) { +void uartputs(uartDev dev,char *s) { while (*s) uartputc(dev,*s++); } -void uartgets(uartDev* dev,char *s) { +void uartgets(uartDev dev,char *s) { while (*s && (*s!=0xd)) *s++ = uartgetc(dev); } @@ -87,16 +87,16 @@ void uarton(int count) -void uartsetup(uartDev* dev,unsigned int baudRate,unsigned char WordLength,unsigned char StopBitCnt,unsigned char Parity) +void uartsetup(uartDev dev,unsigned int baudRate,unsigned char WordLength,unsigned char StopBitCnt,unsigned char Parity) { if(WordLength>9)WordLength=8; if((StopBitCnt>2)||(StopBitCnt==0))StopBitCnt=1; if(Parity>7)Parity=0; - dev->LineCtrl = (WordLength-5) + ((StopBitCnt-1)<<2) + (Parity<<3); + ((_uartDev)dev)->LineCtrl = (WordLength-5) + ((StopBitCnt-1)<<2) + (Parity<<3); uartsetbaudrate(dev,baudRate); } -unsigned char uartgetpclkfactor(uartDev* dev) +unsigned char uartgetpclkfactor(uartDev dev) { unsigned int clksel=0; const char clkselDec[]={4,1,2,8}; @@ -120,7 +120,7 @@ unsigned char uartgetpclkfactor(uartDev* return clkselDec[clksel]; } -void uartsetpclkfactor(uartDev* dev,unsigned char pclkfactor) +void uartsetpclkfactor(uartDev dev,unsigned char pclkfactor) { const char clkselDec[]={1,1,2,2,0,0,0,0,3}; unsigned int clksel=0; @@ -147,7 +147,7 @@ void uartsetpclkfactor(uartDev* dev,unsi } } -void uartsetbaudrate(uartDev* dev,unsigned int baudRate) +void uartsetbaudrate(uartDev dev,unsigned int baudRate) { unsigned int pclk = 0; unsigned int clksel=0; @@ -162,30 +162,37 @@ void uartsetbaudrate(uartDev* dev,unsign uartsetpclkfactor(dev,pclkfact/2); pclk = cpuclk / uartgetpclkfactor(dev); } - dev->LineCtrl |= 128; - dev->RWreg = pclk/(baudRate*16); - dev->LineCtrl &= ~(128); + ((_uartDev)dev)->LineCtrl |= 128; + ((_uartDev)dev)->RWreg = pclk/(baudRate*16); + ((_uartDev)dev)->LineCtrl &= ~(128); } -uartDev* uartopen(int count){ - uartDev* dev; +uartDev uartopen(int count){ + uartDev dev; switch(count) { case 0: - dev = (uartDev*)((unsigned long)UART0_BASE_ADDR); + dev = (uartDev)((unsigned long)UART0_BASE_ADDR); break; case 1: - dev = (uartDev*)((unsigned long)UART1_BASE_ADDR); + dev = (uartDev)((unsigned long)UART1_BASE_ADDR); break; case 2: - dev = (uartDev*)((unsigned long)UART2_BASE_ADDR); + dev = (uartDev)((unsigned long)UART2_BASE_ADDR); break; case 3: - dev = (uartDev*)((unsigned long)UART3_BASE_ADDR); + dev = (uartDev)((unsigned long)UART3_BASE_ADDR); break; default: - dev = (uartDev*)0; + dev = (uartDev)0; break; } return dev; } + + + + + + + diff --git a/lib/src/lpc21XX/UART/uart.h b/lib/src/lpc21XX/UART/uart.h --- a/lib/src/lpc21XX/UART/uart.h +++ b/lib/src/lpc21XX/UART/uart.h @@ -21,7 +21,9 @@ -------------------------------------------------------------------------------*/ #ifndef UART_H #define UART_H + #include "LPC23xx.h" +#include #define uartNoParity 0 @@ -30,7 +32,7 @@ #define uartTrueParity 5 #define uartFalseParity 7 -struct uartRegs +struct LPC17XXuartRegs { unsigned long RWreg; unsigned long IntEN; @@ -41,19 +43,20 @@ struct uartRegs unsigned long ScratchPad; }; -typedef volatile struct uartRegs uartDev; +typedef volatile struct LPC17XXuartRegs* _uartDev; +typedef UHANDLE uartDev; -extern uartDev* uartopen(int count); +extern uartDev uartopen(int count); extern void uarton(int count); extern void uartoff(int count); -extern void uartputc(uartDev* dev,char c); -extern void uartputs(uartDev* dev,char *s); -extern void uartgets(uartDev* dev,char *s); -extern char uartgetc(uartDev* dev); -extern void uartsetbaudrate(uartDev* dev,unsigned int baudRate); -extern unsigned char uartgetpclkfactor(uartDev* dev); -extern void uartsetpclkfactor(uartDev* dev,unsigned char pclkfactor); -extern void uartsetup(uartDev* dev,unsigned int baudRate,unsigned char WordLength,unsigned char StopBitCnt,unsigned char Parity); +extern void uartputc(uartDev dev,char c); +extern void uartputs(uartDev dev,char *s); +extern void uartgets(uartDev dev,char *s); +extern char uartgetc(uartDev dev); +extern void uartsetbaudrate(uartDev dev,unsigned int baudRate); +extern unsigned char uartgetpclkfactor(uartDev dev); +extern void uartsetpclkfactor(uartDev dev,unsigned char pclkfactor); +extern void uartsetup(uartDev dev,unsigned int baudRate,unsigned char WordLength,unsigned char StopBitCnt,unsigned char Parity); #endif diff --git a/lib/src/lpc21XX/UART/uart.pro b/lib/src/lpc21XX/UART/uart.pro --- a/lib/src/lpc21XX/UART/uart.pro +++ b/lib/src/lpc21XX/UART/uart.pro @@ -4,7 +4,7 @@ TARGET = libuart TARGETINSTALLPATH = $(LIBUC_LIBS_DIR)/UART HEADERSINSTALLPATH = $(LIBUC_INC_DIR)/UART -LIBS += CORE +LIBS += CORE UHANDLE SOURCES += uart.c diff --git a/lib/src/lpc21XX/lpc21XX.pro b/lib/src/lpc21XX/lpc21XX.pro --- a/lib/src/lpc21XX/lpc21XX.pro +++ b/lib/src/lpc21XX/lpc21XX.pro @@ -1,3 +1,5 @@ TEMPLATE = dir SUBDIRS += CORE \ - UART + UART \ + IIC \ + SSP diff --git a/lib/src/lpc21XX/old/UART/Makefile b/lib/src/lpc21XX/old/UART/Makefile new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/old/UART/Makefile @@ -0,0 +1,28 @@ + +PROJECTDIR = `pwd` +LIBUC = /opt/libuc2 + +HEADERSINSTALLPATH = $(LIBUC_INC_DIR)/UART +HEADERS += uart.h +LIBSOURCES += uart.c +OBJDIR = obj +BINDIR = bin +OBJECTFILES = $(LIBSOURCES:.c=.o) +OBJECTFILES := $(addprefix $(OBJDIR)/,$(OBJECTFILES)) +ARCH = lpc21XX-arm-noabi-gcc +ARCHFOLDER = $(LIBUC)/rules/lpc21XX-arm-noabi-gcc +TARGET=libuart +LIBUC_INCLUDES=$(LIBUC_INC_DIR_CORE_CMD) +LIBUC_LIBRARIES=$(LIBUC_LIBS_DIR_CORE_CMD) $(LIBUC_LIBS_CORE) +TARGETINSTALLPATH=$(LIBUC_LIBS_DIR)/UART +HEADERSINSTALLPATH=$(LIBUC_INC_DIR)/UART +BSP=generic +include $(ARCHFOLDER)/rules.mk + +all:lib + @echo Code compiled + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(TARGETINSTALLPATH)/*.a + rm -f $(HEADERSINSTALLPATH)/*.h diff --git a/lib/src/lpc21XX/old/UART/uart.c b/lib/src/lpc21XX/old/UART/uart.c new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/old/UART/uart.c @@ -0,0 +1,191 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#include "core.h" +#include "uart.h" + + +void uartputc(uartDev* dev,char c) { + while (!((dev->LineStat & (1<<5)))); + dev->RWreg = c; +} + +char uartgetc(uartDev* dev) { + while (!((dev->LineStat & 1))); + return (char)dev->RWreg; +} + + +void uartputs(uartDev* dev,char *s) { + while (*s) uartputc(dev,*s++); +} + + +void uartgets(uartDev* dev,char *s) { + while (*s && (*s!=0xd)) *s++ = uartgetc(dev); +} + +void uartoff(int count) +{ + switch(count) + { + case 0: + PCONP &= ~( 1 << 3 ); + break; + case 1: + PCONP &= ~( 1 << 4 ); + break; + case 2: + PCONP &= ~( 1 << 24 ); + break; + case 3: + PCONP &= ~( 1 << 25 ); + break; + default: + break; + } +} + +void uarton(int count) +{ + switch(count) + { + case 0: + PCONP |= ( 1 << 3 ); + break; + case 1: + PCONP |= ( 1 << 4 ); + break; + case 2: + PCONP |= ( 1 << 24 ); + break; + case 3: + PCONP |= ( 1 << 25 ); + break; + default: + break; + } +} + + + +void uartsetup(uartDev* dev,unsigned int baudRate,unsigned char WordLength,unsigned char StopBitCnt,unsigned char Parity) +{ + if(WordLength>9)WordLength=8; + if((StopBitCnt>2)||(StopBitCnt==0))StopBitCnt=1; + if(Parity>7)Parity=0; + dev->LineCtrl = (WordLength-5) + ((StopBitCnt-1)<<2) + (Parity<<3); + uartsetbaudrate(dev,baudRate); +} + +unsigned char uartgetpclkfactor(uartDev* dev) +{ + unsigned int clksel=0; + const char clkselDec[]={4,1,2,8}; + switch((int)dev) + { + case (int)UART0_BASE_ADDR: + clksel = (PCLKSEL0>>6) & 3; + break; + case (int)UART1_BASE_ADDR: + clksel = (PCLKSEL0>>8) & 3; + break; + case (int)UART2_BASE_ADDR: + clksel = (PCLKSEL1>>16) & 3; + break; + case (int)UART3_BASE_ADDR: + clksel = (PCLKSEL1>>18) & 3; + break; + default: + break; + } + return clkselDec[clksel]; +} + +void uartsetpclkfactor(uartDev* dev,unsigned char pclkfactor) +{ + const char clkselDec[]={1,1,2,2,0,0,0,0,3}; + unsigned int clksel=0; + switch((int)dev) + { + case (int)UART0_BASE_ADDR: + PCLKSEL0 |= clkselDec[pclkfactor]<<6; + PCLKSEL0 &= clkselDec[pclkfactor]<<6; + break; + case (int)UART1_BASE_ADDR: + PCLKSEL0 |= clkselDec[pclkfactor]<<8; + PCLKSEL0 &= clkselDec[pclkfactor]<<8; + break; + case (int)UART2_BASE_ADDR: + PCLKSEL1 |= clkselDec[pclkfactor]<<16; + PCLKSEL1 &= clkselDec[pclkfactor]<<16; + break; + case (int)UART3_BASE_ADDR: + PCLKSEL1 |= clkselDec[pclkfactor]<<18; + PCLKSEL1 &= clkselDec[pclkfactor]<<18; + break; + default: + break; + } +} + +void uartsetbaudrate(uartDev* dev,unsigned int baudRate) +{ + unsigned int pclk = 0; + unsigned int clksel=0; + unsigned int cpuclk=0; + if(dev==0)return; + cpuclk = coregetCpuFreq(); + pclk = cpuclk / uartgetpclkfactor(dev); + while((baudRate*16)>pclk) + { + unsigned char pclkfact= uartgetpclkfactor(dev); + if(pclkfact==1)return; + uartsetpclkfactor(dev,pclkfact/2); + pclk = cpuclk / uartgetpclkfactor(dev); + } + dev->LineCtrl |= 128; + dev->RWreg = pclk/(baudRate*16); + dev->LineCtrl &= ~(128); +} + +uartDev* uartopen(int count){ + uartDev* dev; + switch(count) + { + case 0: + dev = (uartDev*)((unsigned long)UART0_BASE_ADDR); + break; + case 1: + dev = (uartDev*)((unsigned long)UART1_BASE_ADDR); + break; + case 2: + dev = (uartDev*)((unsigned long)UART2_BASE_ADDR); + break; + case 3: + dev = (uartDev*)((unsigned long)UART3_BASE_ADDR); + break; + default: + dev = (uartDev*)0; + break; + } + return dev; +} diff --git a/lib/src/lpc21XX/old/UART/uart.h b/lib/src/lpc21XX/old/UART/uart.h new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/old/UART/uart.h @@ -0,0 +1,66 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the libuc, microcontroler library +-- Copyright (C) 2011, Alexis Jeandet +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +------------------------------------------------------------------------------- +-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@gmail.com +-------------------------------------------------------------------------------*/ +#ifndef UART_H +#define UART_H +#include "LPC23xx.h" + + +#define uartNoParity 0 +#define uartOddParity 1 +#define uartEvenParity 3 +#define uartTrueParity 5 +#define uartFalseParity 7 + +struct uartRegs +{ + unsigned long RWreg; + unsigned long IntEN; + unsigned long IntIdFIFOctrlr; + unsigned long LineCtrl; + unsigned long dummy; + unsigned long LineStat; + unsigned long ScratchPad; +}; + +typedef volatile struct uartRegs uartDev; + +extern uartDev* uartopen(int count); +extern void uarton(int count); +extern void uartoff(int count); +extern void uartputc(uartDev* dev,char c); +extern void uartputs(uartDev* dev,char *s); +extern void uartgets(uartDev* dev,char *s); +extern char uartgetc(uartDev* dev); +extern void uartsetbaudrate(uartDev* dev,unsigned int baudRate); +extern unsigned char uartgetpclkfactor(uartDev* dev); +extern void uartsetpclkfactor(uartDev* dev,unsigned char pclkfactor); +extern void uartsetup(uartDev* dev,unsigned int baudRate,unsigned char WordLength,unsigned char StopBitCnt,unsigned char Parity); + +#endif + + + + + + + + diff --git a/lib/src/lpc21XX/old/UART/uart.pro b/lib/src/lpc21XX/old/UART/uart.pro new file mode 100644 --- /dev/null +++ b/lib/src/lpc21XX/old/UART/uart.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +ARCH = lpc21XX-arm-noabi-gcc +TARGET = libuart +TARGETINSTALLPATH = $(LIBUC_LIBS_DIR)/UART +HEADERSINSTALLPATH = $(LIBUC_INC_DIR)/UART + +LIBS += CORE + +SOURCES += uart.c + + +HEADERS += uart.h diff --git a/rules/common/libsrules.mk b/rules/common/libsrules.mk new file mode 100644 --- /dev/null +++ b/rules/common/libsrules.mk @@ -0,0 +1,112 @@ +#--------------------------------------------------------------------------------- +# LIBRARY DEFINITIONS +#--------------------------------------------------------------------------------- +LIBUC_LIBS = +LIBUC_LIBS_CORE = -static -lcore +LIBUC_LIBS_UCSTRINGS = -static -lucstrings +LIBUC_LIBS_UART = -static -luart +LIBUC_LIBS_SPI = -static -lspi +LIBUC_LIBS_SSP = -static -lssp +LIBUC_LIBS_IIC = -static -liic +LIBUC_LIBS_ADC = -static -ladc +LIBUC_LIBS_24LC0X = -static -l24lc0X +LIBUC_LIBS_SDCARD = -static -lsdcard +LIBUC_LIBS_BLKDEVICE = -static -lblkdevice +LIBUC_LIBS_FAT32 = -static -lfat32 +LIBUC_LIBS_VS10XX = -static -lvs10XX +LIBUC_LIBS_UHANDLE = -static -luhandle +LIBUC_LIBS_HEXVIEWER = -static -lhexviewer +LIBUC_LIBS_MBR = -static -lmbr +LIBUC_LIBS_UCDIRENT = -static -lucdirent +LIBUC_LIBS_FS = -static -lfs +LIBUC_LIBS_ALLFS = $(LIBUC_LIBS_UCDIRENT) $(LIBUC_LIBS_FS) $(LIBUC_LIBS_MBR) $(LIBUC_LIBS_FAT32) $(LIBUC_LIBS_SDCARD) $(LIBUC_LIBS_BLKDEVICE) +LIBUC_LIBS_FSEXPLORER = -static -lfsexplorer + +LIBUC_LIBS_DIR_CORE = $(LIBUC_LIBS_DIR)/CORE +LIBUC_LIBS_DIR_UCSTRINGS = $(LIBUC_LIBS_DIR)/STRINGS/$(ARCH) +LIBUC_LIBS_DIR_UART = $(LIBUC_LIBS_DIR)/UART +LIBUC_LIBS_DIR_SPI = $(LIBUC_LIBS_DIR)/SPI +LIBUC_LIBS_DIR_SSP = $(LIBUC_LIBS_DIR)/SSP +LIBUC_LIBS_DIR_IIC = $(LIBUC_LIBS_DIR)/IIC +LIBUC_LIBS_DIR_ADC = $(LIBUC_LIBS_DIR)/ADC +LIBUC_LIBS_DIR_24LC0X = $(LIBUC_LIBS_DIR)/24LCXX/24LC0X +LIBUC_LIBS_DIR_SDCARD = $(LIBUC_LIBS_DIR)/SDCARD +LIBUC_LIBS_DIR_VS10XX = $(LIBUC_LIBS_DIR)/VS10XX +LIBUC_LIBS_DIR_BLKDEVICE = $(LIBUC_LIBS_DIR)/BLKDEVICE +LIBUC_LIBS_DIR_FAT32 = $(LIBUC_LIBS_DIR)/FAT32 +LIBUC_LIBS_DIR_UHANDLE = $(LIBUC_LIBS_DIR)/UHANDLE +LIBUC_LIBS_DIR_HEXVIEWER = $(LIBUC_LIBS_DIR)/HEXVIEWER +LIBUC_LIBS_DIR_MBR = $(LIBUC_LIBS_DIR)/MBR +LIBUC_LIBS_DIR_UCDIRENT = $(LIBUC_LIBS_DIR)/UCDIRENT +LIBUC_LIBS_DIR_FS = $(LIBUC_LIBS_DIR)/FS +LIBUC_LIBS_DIR_FSEXPLORER = $(LIBUC_LIBS_DIR)/FSEXPLORER + +LIBUC_LIBS_DIR_CORE_CMD = -L $(LIBUC_LIBS_DIR_CORE) +LIBUC_LIBS_DIR_UCSTRINGS_CMD = -L $(LIBUC_LIBS_DIR_UCSTRINGS) +LIBUC_LIBS_DIR_UART_CMD = -L $(LIBUC_LIBS_DIR_UART) +LIBUC_LIBS_DIR_SPI_CMD = -L $(LIBUC_LIBS_DIR_SPI) +LIBUC_LIBS_DIR_SSP_CMD = -L $(LIBUC_LIBS_DIR_SSP) +LIBUC_LIBS_DIR_IIC_CMD = -L $(LIBUC_LIBS_DIR_IIC) +LIBUC_LIBS_DIR_ADC_CMD = -L $(LIBUC_LIBS_DIR_ADC) +LIBUC_LIBS_DIR_24LC0X_CMD = -L $(LIBUC_LIBS_DIR_24LC0X) +LIBUC_LIBS_DIR_SDCARD_CMD = -L $(LIBUC_LIBS_DIR_SDCARD) +LIBUC_LIBS_DIR_VS10XX_CMD = -L $(LIBUC_LIBS_DIR_VS10XX) +LIBUC_LIBS_DIR_BLKDEVICE_CMD = -L $(LIBUC_LIBS_DIR_BLKDEVICE) +LIBUC_LIBS_DIR_FAT32_CMD = -L $(LIBUC_LIBS_DIR_FAT32) +LIBUC_LIBS_DIR_UHANDLE_CMD = -L $(LIBUC_LIBS_DIR_UHANDLE) +LIBUC_LIBS_DIR_HEXVIEWER_CMD = -L $(LIBUC_LIBS_DIR_HEXVIEWER) +LIBUC_LIBS_DIR_MBR_CMD = -L $(LIBUC_LIBS_DIR_MBR) +LIBUC_LIBS_DIR_UCDIRENT_CMD = -L $(LIBUC_LIBS_DIR_UCDIRENT) +LIBUC_LIBS_DIR_FS_CMD = -L $(LIBUC_LIBS_DIR_FS) +LIBUC_LIBS_DIR_ALLFS_CMD = $(LIBUC_LIBS_DIR_UCDIRENT_CMD) $(LIBUC_LIBS_DIR_FS_CMD) $(LIBUC_LIBS_DIR_MBR_CMD) $(LIBUC_LIBS_DIR_FAT32_CMD) $(LIBUC_LIBS_DIR_SDCARD_CMD) $(LIBUC_LIBS_DIR_BLKDEVICE_CMD) +LIBUC_LIBS_DIR_FSEXPLORER_CMD = -L $(LIBUC_LIBS_DIR_FSEXPLORER) + +LIBUC_INC_DIR_CORE = $(LIBUC_INC_DIR)/CORE +LIBUC_INC_DIR_UCSTRINGS = $(LIBUC_INC_DIR)/STRINGS/$(ARCH) +LIBUC_INC_DIR_UART = $(LIBUC_INC_DIR)/UART +LIBUC_INC_DIR_SPI = $(LIBUC_INC_DIR)/SPI +LIBUC_INC_DIR_SSP = $(LIBUC_INC_DIR)/SSP +LIBUC_INC_DIR_IIC = $(LIBUC_INC_DIR)/IIC +LIBUC_INC_DIR_ADC = $(LIBUC_INC_DIR)/ADC +LIBUC_INC_DIR_24LC0X = $(LIBUC_INC_DIR)/24LCXX/24LC0X +LIBUC_INC_DIR_SDCARD = $(LIBUC_INC_DIR)/SDCARD +LIBUC_INC_DIR_VS10XX = $(LIBUC_INC_DIR)/VS10XX +LIBUC_INC_DIR_BLKDEVICE = $(LIBUC_INC_DIR)/BLKDEVICE +LIBUC_INC_DIR_FAT32 = $(LIBUC_INC_DIR)/FAT32 +LIBUC_INC_DIR_UHANDLE = $(LIBUC_INC_DIR)/UHANDLE +LIBUC_INC_DIR_HEXVIEWER = $(LIBUC_INC_DIR)/HEXVIEWER +LIBUC_INC_DIR_MBR = $(LIBUC_INC_DIR)/MBR +LIBUC_INC_DIR_UCDIRENT = $(LIBUC_INC_DIR)/UCDIRENT +LIBUC_INC_DIR_FS = $(LIBUC_INC_DIR)/FS +LIBUC_INC_DIR_FSEXPLORER = $(LIBUC_INC_DIR)/FSEXPLORER + +LIBUC_INC_DIR_CORE_CMD = -I $(LIBUC_INC_DIR_CORE) +LIBUC_INC_DIR_UCSTRINGS_CMD = -I $(LIBUC_INC_DIR_UCSTRINGS) +LIBUC_INC_DIR_UART_CMD = -I $(LIBUC_INC_DIR_UART) +LIBUC_INC_DIR_SPI_CMD = -I $(LIBUC_INC_DIR_SPI) +LIBUC_INC_DIR_SSP_CMD = -I $(LIBUC_INC_DIR_SSP) +LIBUC_INC_DIR_IIC_CMD = -I $(LIBUC_INC_DIR_IIC) +LIBUC_INC_DIR_ADC_CMD = -I $(LIBUC_INC_DIR_ADC) +LIBUC_INC_DIR_24LC0X_CMD = -I $(LIBUC_INC_DIR_24LC0X) +LIBUC_INC_DIR_SDCARD_CMD = -I $(LIBUC_INC_DIR_SDCARD) +LIBUC_INC_DIR_VS10XX_CMD = -I $(LIBUC_INC_DIR_VS10XX) +LIBUC_INC_DIR_BLKDEVICE_CMD = -I $(LIBUC_INC_DIR_BLKDEVICE) +LIBUC_INC_DIR_FAT32_CMD = -I $(LIBUC_INC_DIR_FAT32) +LIBUC_INC_DIR_UHANDLE_CMD = -I $(LIBUC_INC_DIR_UHANDLE) +LIBUC_INC_DIR_HEXVIEWER_CMD = -I $(LIBUC_INC_DIR_HEXVIEWER) +LIBUC_INC_DIR_MBR_CMD = -I $(LIBUC_INC_DIR_MBR) +LIBUC_INC_DIR_UCDIRENT_CMD = -I $(LIBUC_INC_DIR_UCDIRENT) +LIBUC_INC_DIR_FS_CMD = -I $(LIBUC_INC_DIR_FS) +LIBUC_INC_DIR_ALLFS_CMD = $(LIBUC_INC_DIR_UCDIRENT_CMD) $(LIBUC_INC_DIR_FS_CMD) $(LIBUC_INC_DIR_MBR_CMD) $(LIBUC_INC_DIR_FAT32_CMD) $(LIBUC_INC_DIR_SDCARD_CMD) $(LIBUC_INC_DIR_BLKDEVICE_CMD) +LIBUC_INC_DIR_FSEXPLORER_CMD = -I $(LIBUC_INC_DIR_FSEXPLORER) + + + + + + + + + + + diff --git a/rules/lpc17XX-arm-noabi-gcc/LPC17xx.ld b/rules/lpc17XX-arm-noabi-gcc/LPC17xx.ld --- a/rules/lpc17XX-arm-noabi-gcc/LPC17xx.ld +++ b/rules/lpc17XX-arm-noabi-gcc/LPC17xx.ld @@ -21,7 +21,7 @@ MEMORY /* AHB SRAM - 16k for LPC1756 - often used for USB */ IRAM1 (rwx) : ORIGIN = 0x2007C000, LENGTH = 16k - IRAM2 (rwx) : ORIGIN = 0x20080000, LENGTH = 16k + IRAM2 (rwx) : ORIGIN = 0x20080000, LENGTH = 16k } /* SECTION command : Define mapping of input sections */ diff --git a/rules/lpc17XX-arm-noabi-gcc/rules.mk b/rules/lpc17XX-arm-noabi-gcc/rules.mk --- a/rules/lpc17XX-arm-noabi-gcc/rules.mk +++ b/rules/lpc17XX-arm-noabi-gcc/rules.mk @@ -72,68 +72,9 @@ LIBUC_CXXFLAGS_HARD_FPU = # LIBRARY DEFINITIONS #--------------------------------------------------------------------------------- -LIBUC_LIBS = -LIBUC_LIBS_CORE = -static -lcore -LIBUC_LIBS_UCSTRINGS = -static -lucstrings -LIBUC_LIBS_UART = -static -luart -LIBUC_LIBS_SPI = -static -lspi -LIBUC_LIBS_SSP = -static -lssp -LIBUC_LIBS_IIC = -static -liic -LIBUC_LIBS_ADC = -static -ladc -LIBUC_LIBS_24LC0X = -static -l24lc0X -LIBUC_LIBS_SDCARD = -static -lsdcard -LIBUC_LIBS_BLKDEVICE = -static -lblkdevice -LIBUC_LIBS_VS10XX = -static -lvs10XX - LIBUC_LIBS_DIR = $(LIBUC)/lib/bin/lpc17XX -LIBUC_LIBS_DIR_CORE = $(LIBUC_LIBS_DIR)/CORE -LIBUC_LIBS_DIR_UCSTRINGS = $(LIBUC_LIBS_DIR)/STRINGS/$(ARCH) -LIBUC_LIBS_DIR_UART = $(LIBUC_LIBS_DIR)/UART -LIBUC_LIBS_DIR_SPI = $(LIBUC_LIBS_DIR)/SPI -LIBUC_LIBS_DIR_SSP = $(LIBUC_LIBS_DIR)/SSP -LIBUC_LIBS_DIR_IIC = $(LIBUC_LIBS_DIR)/IIC -LIBUC_LIBS_DIR_ADC = $(LIBUC_LIBS_DIR)/ADC -LIBUC_LIBS_DIR_24LC0X = $(LIBUC_LIBS_DIR)/24LCXX/24LC0X -LIBUC_LIBS_DIR_SDCARD = $(LIBUC_LIBS_DIR)/SDCARD -LIBUC_LIBS_DIR_VS10XX = $(LIBUC_LIBS_DIR)/VS10XX -LIBUC_LIBS_DIR_BLKDEVICE = $(LIBUC_LIBS_DIR)/BLKDEVICE - -LIBUC_LIBS_DIR_CORE_CMD = -L $(LIBUC_LIBS_DIR_CORE) -LIBUC_LIBS_DIR_UCSTRINGS_CMD = -L $(LIBUC_LIBS_DIR_UCSTRINGS) -LIBUC_LIBS_DIR_UART_CMD = -L $(LIBUC_LIBS_DIR_UART) -LIBUC_LIBS_DIR_SPI_CMD = -L $(LIBUC_LIBS_DIR_SPI) -LIBUC_LIBS_DIR_SSP_CMD = -L $(LIBUC_LIBS_DIR_SSP) -LIBUC_LIBS_DIR_IIC_CMD = -L $(LIBUC_LIBS_DIR_IIC) -LIBUC_LIBS_DIR_ADC_CMD = -L $(LIBUC_LIBS_DIR_ADC) -LIBUC_LIBS_DIR_24LC0X_CMD = -L $(LIBUC_LIBS_DIR_24LC0X) -LIBUC_LIBS_DIR_SDCARD_CMD = -L $(LIBUC_LIBS_DIR_SDCARD) -LIBUC_LIBS_DIR_VS10XX_CMD = -L $(LIBUC_LIBS_DIR_VS10XX) -LIBUC_LIBS_DIR_BLKDEVICE_CMD = -L $(LIBUC_LIBS_DIR_BLKDEVICE) - LIBUC_INC_DIR = $(LIBUC)/lib/includes/lpc17XX -LIBUC_INC_DIR_CORE = $(LIBUC_INC_DIR)/CORE -LIBUC_INC_DIR_UCSTRINGS = $(LIBUC_INC_DIR)/STRINGS/$(ARCH) -LIBUC_INC_DIR_UART = $(LIBUC_INC_DIR)/UART -LIBUC_INC_DIR_SPI = $(LIBUC_INC_DIR)/SPI -LIBUC_INC_DIR_SSP = $(LIBUC_INC_DIR)/SSP -LIBUC_INC_DIR_IIC = $(LIBUC_INC_DIR)/IIC -LIBUC_INC_DIR_ADC = $(LIBUC_INC_DIR)/ADC -LIBUC_INC_DIR_24LC0X = $(LIBUC_INC_DIR)/24LCXX/24LC0X -LIBUC_INC_DIR_SDCARD = $(LIBUC_INC_DIR)/SDCARD -LIBUC_INC_DIR_VS10XX = $(LIBUC_INC_DIR)/VS10XX -LIBUC_INC_DIR_BLKDEVICE = $(LIBUC_INC_DIR)/BLKDEVICE - -LIBUC_INC_DIR_CORE_CMD = -I $(LIBUC_INC_DIR_CORE) -LIBUC_INC_DIR_UCSTRINGS_CMD = -I $(LIBUC_INC_DIR_UCSTRINGS) -LIBUC_INC_DIR_UART_CMD = -I $(LIBUC_INC_DIR_UART) -LIBUC_INC_DIR_SPI_CMD = -I $(LIBUC_INC_DIR_SPI) -LIBUC_INC_DIR_SSP_CMD = -I $(LIBUC_INC_DIR_SSP) -LIBUC_INC_DIR_IIC_CMD = -I $(LIBUC_INC_DIR_IIC) -LIBUC_INC_DIR_ADC_CMD = -I $(LIBUC_INC_DIR_ADC) -LIBUC_INC_DIR_24LC0X_CMD = -I $(LIBUC_INC_DIR_24LC0X) -LIBUC_INC_DIR_SDCARD_CMD = -I $(LIBUC_INC_DIR_SDCARD) -LIBUC_INC_DIR_VS10XX_CMD = -I $(LIBUC_INC_DIR_VS10XX) -LIBUC_INC_DIR_BLKDEVICE_CMD = -I $(LIBUC_INC_DIR_BLKDEVICE) +include $(LIBUC)/rules/common/libsrules.mk #--------------------------------------------------------------------------------- # BOARD SUPORT PACKAGES @@ -147,7 +88,11 @@ LIBUC_BSP_INC = -I $(LIBUC_BSP_INC_DIR)/ # DEVICE SPECIAL FILES #--------------------------------------------------------------------------------- LINKER_SCRIPT = $(ARCHFOLDER)/LPC17xx.ld -APPSOURCES += $(ARCHFOLDER)/startup_LPC17xx.c $(ARCHFOLDER)/core_cm3.c $(ARCHFOLDER)/system_LPC17xx.c +DEVSOURCES += $(ARCHFOLDER)/startup_LPC17xx.c $(ARCHFOLDER)/core_cm3.c $(ARCHFOLDER)/system_LPC17xx.c +DEVSOURCESND = $(notdir $(DEVSOURCES)) +DEVOBJECTFILES += $(DEVSOURCESND:.c=.o) +DEVOBJECTFILES := $(addprefix $(OBJDIR)/,$(DEVOBJECTFILES)) +OBJECTFILES += $(DEVOBJECTFILES) LPC17XX_INCDIR=$(ARCHFOLDER) @@ -159,34 +104,43 @@ all: @echo "lpc17XX-arm-noabi-gcc rules" -bin: $(TARGET).bin $(TARGET).hex +bin: $(DEVSOURCESND) $(BINDIR)/$(TARGET).bin $(BINDIR)/$(TARGET).hex @echo "compile bin" - +$(DEVSOURCESND): $(DEVSOURCES) + cp $(DEVSOURCES) ./ -lib: $(TARGET).a +lib: $(TARGETINSTALLPATH)/$(TARGET).a @echo "compile lib" %.a: $(OBJECTFILES) mkdir -p $(TARGETINSTALLPATH) mkdir -p $(HEADERSINSTALLPATH) - $(LIBUC_AR) rcs $(TARGETINSTALLPATH)/$@ $(OBJECTFILES) + $(LIBUC_AR) rcs $@ $(OBJECTFILES) #$(LIBUC_AR) rcs $(TARGETINSTALLPATH)/$@ $(OBJECTFILES) cp -f $(HEADERS) $(HEADERSINSTALLPATH)/ -%.o: %.c +#%.o: %.c +# $(LIBUC_CC) -O3 -I $(LPC17XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -MM $< -MF $*.d -MP +# $(LIBUC_CC) -O3 -I $(LPC17XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -c $(LIBUC_CFLAGS) $< -o $@ + +$(OBJECTFILES) : $(OBJDIR)/%.o : %.c $(INC_LIBS_DEPS) $(HEADERS) + mkdir -p $(OBJDIR) $(LIBUC_CC) -O3 -I $(LPC17XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -MM $< -MF $*.d -MP $(LIBUC_CC) -O3 -I $(LPC17XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -c $(LIBUC_CFLAGS) $< -o $@ - + %.elf: $(LINKER_SCRIPT) $(OBJECTFILES) + mkdir -p $(BINDIR) $(LIBUC_LD) -Map $(@:.elf=.map) $(LIBUC_LDFLAGS) -T $^ -o $@ $(LIBUC_BSP) $(LIBUC_LIBRARIES) $(LIBUC_OBJDUMP) $(LIBUC_ODFLAGS) $@ > $(@:.elf=.dump) $(LIBUC_SIZE) $@ -%.bin: %.elf + +%.bin: %.elf $(BIN_LIBS_DEPS) $(LIBUC_OBJCOPY) $(LIBUC_CPFLAGS) -O binary $< $*.bin - + @echo "BIN_LIBS_DEPS" + @echo $(BIN_LIBS_DEPS) %.hex: %.elf $(LIBUC_OBJCOPY) $(LIBUC_CPFLAGS) -O ihex $< $*.hex @@ -194,6 +148,13 @@ lib: $(TARGET).a clean: rm -f *.o *.d *.bin *.hex *.dump *.map *.a + rm -f $(OBJECTFILES) + rm -f $(BINDIR)/*.bin + rm -f $(BINDIR)/*.hex + rm -f $(BINDIR)/*.dump + rm -f $(BINDIR)/*.map + rm -f $(BINDIR)/*.a + rm -f $(DEVSOURCESND) distclean: rm -f $(TARGETINSTALLPATH)/*.bin diff --git a/rules/lpc17XX-arm-noabi-gcc/startup_LPC17xx.c b/rules/lpc17XX-arm-noabi-gcc/startup_LPC17xx.c --- a/rules/lpc17XX-arm-noabi-gcc/startup_LPC17xx.c +++ b/rules/lpc17XX-arm-noabi-gcc/startup_LPC17xx.c @@ -110,8 +110,8 @@ extern int main(void); * 0x0000.0000. * ******************************************************************************/ -#define STACK_SIZE 0x00000200 - +#define STACK_SIZE 0x00000800 /*2kO*/ + __attribute__ ((section(".stackarea"))) /* static */ unsigned long pulStack[STACK_SIZE]; diff --git a/rules/lpc21XX-arm-noabi-gcc/LPC2378-RAM.ld b/rules/lpc21XX-arm-noabi-gcc/LPC2378-RAM.ld new file mode 100644 --- /dev/null +++ b/rules/lpc21XX-arm-noabi-gcc/LPC2378-RAM.ld @@ -0,0 +1,127 @@ +/***********************************************************************/ +/* */ +/* RAM.ld: Linker Script File */ +/* */ +/***********************************************************************/ + +ENTRY(_start) +STACK_SIZE = 0x800; + +/* Memory Definitions */ +/* lpc2378 mt */ +MEMORY +{ + ROM (rx) : ORIGIN = 0x00000000, LENGTH = 512K + RAM (rw) : ORIGIN = 0x40000000, LENGTH = 32K +} + +/* Section Definitions */ +SECTIONS +{ + /* first section is .text which is used for code */ + .text : + { + *crt0.o (.text) /* Startup code */ + *(.text) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + } > RAM + + . = ALIGN(4); + + /* .ctors .dtors are used for c++ constructors/destructors */ + /* added by Martin Thomas 4/2005 based on Anglia Design example */ + .ctors : + { + PROVIDE(__ctors_start__ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(__ctors_end__ = .); + } >RAM + + .dtors : + { + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + } >RAM + + . = ALIGN(4); + /* mthomas - end */ + + _etext = . ; + PROVIDE (etext = .); + + /* .data section which is used for initialized data */ + .data : + { + _data = .; + *(.data) + } > RAM + + . = ALIGN(4); + _edata = . ; + PROVIDE (edata = .); + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + __bss_start = . ; + __bss_start__ = . ; + *(.bss) + *(COMMON) + . = ALIGN(4); + } > RAM + + . = ALIGN(4); + __bss_end__ = . ; + PROVIDE (__bss_end = .); + + /* .stack ALIGN(256) : */ + .stack : + { + . = ALIGN(256); + . += STACK_SIZE; + PROVIDE (_stack = .); + } > RAM + + _end = . ; + PROVIDE (end = .); + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/rules/lpc21XX-arm-noabi-gcc/LPC2378-ROM.ld b/rules/lpc21XX-arm-noabi-gcc/LPC2378-ROM.ld new file mode 100644 --- /dev/null +++ b/rules/lpc21XX-arm-noabi-gcc/LPC2378-ROM.ld @@ -0,0 +1,128 @@ +/***********************************************************************/ +/* */ +/* ROM.ld: Linker Script File */ +/* */ +/***********************************************************************/ +ENTRY(_boot) +STACK_SIZE = 0x400; + +/* Memory Definitions */ +/* lpc2378 mt */ +MEMORY +{ + ROM (rx) : ORIGIN = 0x00000000, LENGTH = 500K + RAM (rw) : ORIGIN = 0x40000000, LENGTH = (0x00008000 - 0x00000400 - 0x20 - 0x100) +} + +/* Section Definitions */ +SECTIONS +{ + /* first section is .text which is used for code */ + .text : + { + *crt0.o (.text) /* Startup code */ + *(.text) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + } > ROM + + . = ALIGN(4); + + /* .ctors .dtors are used for c++ constructors/destructors */ + /* added by Martin Thomas 4/2005 based on Anglia Design example */ + .ctors : + { + PROVIDE(__ctors_start__ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(__ctors_end__ = .); + } >ROM + + .dtors : + { + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + } >ROM + + . = ALIGN(4); + /* mthomas - end */ + + + _etext = . ; + PROVIDE (etext = .); + + /* .data section which is used for initialized data */ + .data : AT (_etext) + { + _data = .; + *(.data) + SORT(CONSTRUCTORS) /* mt 4/2005 */ + } > RAM + + . = ALIGN(4); + _edata = . ; + PROVIDE (edata = .); + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + __bss_start = . ; + __bss_start__ = . ; + *(.bss) + *(COMMON) + . = ALIGN(4); + } > RAM + + . = ALIGN(4); + __bss_end__ = . ; + PROVIDE (__bss_end = .); + + /* .stack ALIGN(256) : */ + .stack : + { + . = ALIGN(256); + . += STACK_SIZE; + PROVIDE (_stack = .); + } > RAM + + _end = . ; + PROVIDE (end = .); + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/rules/lpc21XX-arm-noabi-gcc/crt0.S b/rules/lpc21XX-arm-noabi-gcc/crt0.S new file mode 100644 --- /dev/null +++ b/rules/lpc21XX-arm-noabi-gcc/crt0.S @@ -0,0 +1,193 @@ + .global main // int main(void) + + .global _etext // -> .data initial values in ROM + .global _data // -> .data area in RAM + .global _edata // end of .data area + .global __bss_start // -> .bss area in RAM + .global __bss_end__ // end of .bss area + .global _stack // top of stack + +// Stack Sizes + .set UND_STACK_SIZE, 0x00000004 + .set ABT_STACK_SIZE, 0x00000004 + .set FIQ_STACK_SIZE, 0x00000004 + .set IRQ_STACK_SIZE, 0X00000080 + .set SVC_STACK_SIZE, 0x00000004 + +// Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs + .set MODE_USR, 0x10 // User Mode + .set MODE_FIQ, 0x11 // FIQ Mode + .set MODE_IRQ, 0x12 // IRQ Mode + .set MODE_SVC, 0x13 // Supervisor Mode + .set MODE_ABT, 0x17 // Abort Mode + .set MODE_UND, 0x1B // Undefined Mode + .set MODE_SYS, 0x1F // System Mode + + .equ I_BIT, 0x80 // when I bit is set, IRQ is disabled + .equ F_BIT, 0x40 // when F bit is set, FIQ is disabled + + .text + .code 32 + .align 2 + + .global _boot + .func _boot +_boot: + +// Runtime Interrupt Vectors +// ------------------------- +Vectors: + b _start // reset - _start + ldr pc,_undf // undefined - _undf + ldr pc,_swi // SWI - _swi + ldr pc,_pabt // program abort - _pabt + ldr pc,_dabt // data abort - _dabt + nop // reserved + ldr pc,[pc,#-0xFF0] // IRQ - read the VIC + ldr pc,_fiq // FIQ - _fiq + +#if 0 +// Use this group for production +_undf: .word _reset // undefined - _reset +_swi: .word _reset // SWI - _reset +_pabt: .word _reset // program abort - _reset +_dabt: .word _reset // data abort - _reset +_irq: .word _reset // IRQ - _reset +_fiq: .word _reset // FIQ - _reset + +#else +// Use this group for development +_undf: .word __undf // undefined +_swi: .word __swi // SWI +_pabt: .word __pabt // program abort +_dabt: .word __dabt // data abort +_irq: .word __irq // IRQ +_fiq: .word __fiq // FIQ + +__undf: b . // undefined +__swi: b . // SWI +__pabt: b . // program abort +__dabt: b . // data abort +__irq: b . // IRQ +__fiq: b . // FIQ +#endif + .size _boot, . - _boot + .endfunc + + +// Setup the operating mode & stack. +// --------------------------------- + .global _start, start, _mainCRTStartup + .func _start + +_start: +start: +_mainCRTStartup: + +// Initialize Interrupt System +// - Set stack location for each mode +// - Leave in System Mode with Interrupts Disabled +// ----------------------------------------------- + ldr r0,=_stack + msr CPSR_c,#MODE_UND|I_BIT|F_BIT // Undefined Instruction Mode + mov sp,r0 + sub r0,r0,#UND_STACK_SIZE + msr CPSR_c,#MODE_ABT|I_BIT|F_BIT // Abort Mode + mov sp,r0 + sub r0,r0,#ABT_STACK_SIZE + msr CPSR_c,#MODE_FIQ|I_BIT|F_BIT // FIQ Mode + mov sp,r0 + sub r0,r0,#FIQ_STACK_SIZE + msr CPSR_c,#MODE_IRQ|I_BIT|F_BIT // IRQ Mode + mov sp,r0 + sub r0,r0,#IRQ_STACK_SIZE + msr CPSR_c,#MODE_SVC|I_BIT|F_BIT // Supervisor Mode + mov sp,r0 + sub r0,r0,#SVC_STACK_SIZE + msr CPSR_c,#MODE_SYS|I_BIT|F_BIT // System Mode + mov sp,r0 + +// Copy initialized data to its execution address in RAM +// ----------------------------------------------------- +#ifdef ROM_RUN + ldr r1,=_etext // -> ROM data start + ldr r2,=_data // -> data start + ldr r3,=_edata // -> end of data +1: cmp r2,r3 // check if data to move + ldrlo r0,[r1],#4 // copy it + strlo r0,[r2],#4 + blo 1b // loop until done +#endif +// Clear .bss +// ---------- + mov r0,#0 // get a zero + ldr r1,=__bss_start // -> bss start + ldr r2,=__bss_end__ // -> bss end +2: cmp r1,r2 // check if data to clear + strlo r0,[r1],#4 // clear 4 bytes + blo 2b // loop until done + +/* + Call C++ constructors (for objects in "global scope") + ctor loop added by Martin Thomas 4/2005 + based on a Anglia Design example-application for ST ARM +*/ + + LDR r0, =__ctors_start__ + LDR r1, =__ctors_end__ +ctor_loop: + CMP r0, r1 + BEQ ctor_end + LDR r2, [r0], #4 + STMFD sp!, {r0-r1} + MOV lr, pc + MOV pc, r2 + LDMFD sp!, {r0-r1} + B ctor_loop +ctor_end: + +// Call main program: main(0) +// -------------------------- + mov r0,#0 // no arguments (argc = 0) + mov r1,r0 + mov r2,r0 + mov fp,r0 // null frame pointer + mov r7,r0 // null frame pointer for thumb + ldr r10,=main + mov lr,pc + bx r10 // enter main() + +/* "global object"-dtors are never called and it should not be + needed since there is no OS to exit to. */ + + .size _start, . - _start + .endfunc + + .global _reset, reset, exit, abort + .func _reset +_reset: +reset: +exit: +abort: +#if 0 +// Disable interrupts, then force a hardware reset by driving P23 low +// ------------------------------------------------------------------- + mrs r0,cpsr // get PSR + orr r0,r0,#I_BIT|F_BIT // disable IRQ and FIQ + msr cpsr,r0 // set up status register + + ldr r1,=(PS_BASE) // PS Base Address + ldr r0,=(PS_PIO) // PIO Module + str r0,[r1,#PS_PCER_OFF] // enable its clock + ldr r1,=(PIO_BASE) // PIO Base Address + ldr r0,=(1<<23) // P23 + str r0,[r1,#PIO_PER_OFF] // make sure pin is contolled by PIO + str r0,[r1,#PIO_CODR_OFF] // set the pin low + str r0,[r1,#PIO_OER_OFF] // make it an output +#endif + b . // loop until reset + + .size _reset, . - _reset + .endfunc + + .end diff --git a/rules/lpc21XX-arm-noabi-gcc/rules.mk b/rules/lpc21XX-arm-noabi-gcc/rules.mk --- a/rules/lpc21XX-arm-noabi-gcc/rules.mk +++ b/rules/lpc21XX-arm-noabi-gcc/rules.mk @@ -42,9 +42,9 @@ LIBUC_OBJDUMP=$(LIBUC_PREFIX)objdump #--------------------------------------------------------------------------------- LIBUC_FMCU = -mcpu=arm7tdmi LIBUC_CFLAGS = $(LIBUC_FMCU) -LIBUC_CFLAGS = -g -gdwarf-2 $(LIBUC_FMCU) -LIBUC_CFLAGS += -Wall -Wextra -Wundef -Wcast-align -LIBUC_LDFLAGS = --gc-sections +LIBUC_CFLAGS += -g -gdwarf-2 -fomit-frame-pointer +LIBUC_CFLAGS += -Wall -Wextra -Wundef -Wcast-align -DROM_RUN +LIBUC_LDFLAGS = -nostartfiles LIBUC_ODFLAGS = -x --syms LIBUC_CPFLAGS = LIBUC_CFLAGS_WARN_ON = -Wall @@ -68,72 +68,14 @@ LIBUC_CXXFLAGS_STATIC_LIB = -fPIC LIBUC_CXXFLAGS_SOFT_FPU = -msoft-float LIBUC_CXXFLAGS_HARD_FPU = + #--------------------------------------------------------------------------------- # LIBRARY DEFINITIONS #--------------------------------------------------------------------------------- - -LIBUC_LIBS = -LIBUC_LIBS_CORE = -static -lcore -LIBUC_LIBS_UCSTRINGS = -static -lucstrings -LIBUC_LIBS_UART = -static -luart -LIBUC_LIBS_SPI = -static -lspi -LIBUC_LIBS_SSP = -static -lssp -LIBUC_LIBS_IIC = -static -liic -LIBUC_LIBS_ADC = -static -ladc -LIBUC_LIBS_24LC0X = -static -l24lc0X -LIBUC_LIBS_SDCARD = -static -lsdcard -LIBUC_LIBS_BLKDEVICE = -static -lblkdevice -LIBUC_LIBS_VS10XX = -static -lvs10XX - LIBUC_LIBS_DIR = $(LIBUC)/lib/bin/lpc21XX -LIBUC_LIBS_DIR_CORE = $(LIBUC_LIBS_DIR)/CORE -LIBUC_LIBS_DIR_UCSTRINGS = $(LIBUC_LIBS_DIR)/STRINGS/$(ARCH) -LIBUC_LIBS_DIR_UART = $(LIBUC_LIBS_DIR)/UART -LIBUC_LIBS_DIR_SPI = $(LIBUC_LIBS_DIR)/SPI -LIBUC_LIBS_DIR_SSP = $(LIBUC_LIBS_DIR)/SSP -LIBUC_LIBS_DIR_IIC = $(LIBUC_LIBS_DIR)/IIC -LIBUC_LIBS_DIR_ADC = $(LIBUC_LIBS_DIR)/ADC -LIBUC_LIBS_DIR_24LC0X = $(LIBUC_LIBS_DIR)/24LCXX/24LC0X -LIBUC_LIBS_DIR_SDCARD = $(LIBUC_LIBS_DIR)/SDCARD -LIBUC_LIBS_DIR_VS10XX = $(LIBUC_LIBS_DIR)/VS10XX -LIBUC_LIBS_DIR_BLKDEVICE = $(LIBUC_LIBS_DIR)/BLKDEVICE +LIBUC_INC_DIR = $(LIBUC)/lib/includes/lpc21XX +include $(LIBUC)/rules/common/libsrules.mk -LIBUC_LIBS_DIR_CORE_CMD = -L $(LIBUC_LIBS_DIR_CORE) -LIBUC_LIBS_DIR_UCSTRINGS_CMD = -L $(LIBUC_LIBS_DIR_UCSTRINGS) -LIBUC_LIBS_DIR_UART_CMD = -L $(LIBUC_LIBS_DIR_UART) -LIBUC_LIBS_DIR_SPI_CMD = -L $(LIBUC_LIBS_DIR_SPI) -LIBUC_LIBS_DIR_SSP_CMD = -L $(LIBUC_LIBS_DIR_SSP) -LIBUC_LIBS_DIR_IIC_CMD = -L $(LIBUC_LIBS_DIR_IIC) -LIBUC_LIBS_DIR_ADC_CMD = -L $(LIBUC_LIBS_DIR_ADC) -LIBUC_LIBS_DIR_24LC0X_CMD = -L $(LIBUC_LIBS_DIR_24LC0X) -LIBUC_LIBS_DIR_SDCARD_CMD = -L $(LIBUC_LIBS_DIR_SDCARD) -LIBUC_LIBS_DIR_VS10XX_CMD = -L $(LIBUC_LIBS_DIR_VS10XX) -LIBUC_LIBS_DIR_BLKDEVICE_CMD = -L $(LIBUC_LIBS_DIR_BLKDEVICE) - -LIBUC_INC_DIR = $(LIBUC)/lib/includes/lpc21XX -LIBUC_INC_DIR_CORE = $(LIBUC_INC_DIR)/CORE -LIBUC_INC_DIR_UCSTRINGS = $(LIBUC_INC_DIR)/STRINGS/$(ARCH) -LIBUC_INC_DIR_UART = $(LIBUC_INC_DIR)/UART -LIBUC_INC_DIR_SPI = $(LIBUC_INC_DIR)/SPI -LIBUC_INC_DIR_SSP = $(LIBUC_INC_DIR)/SSP -LIBUC_INC_DIR_IIC = $(LIBUC_INC_DIR)/IIC -LIBUC_INC_DIR_ADC = $(LIBUC_INC_DIR)/ADC -LIBUC_INC_DIR_24LC0X = $(LIBUC_INC_DIR)/24LCXX/24LC0X -LIBUC_INC_DIR_SDCARD = $(LIBUC_INC_DIR)/SDCARD -LIBUC_INC_DIR_VS10XX = $(LIBUC_INC_DIR)/VS10XX -LIBUC_INC_DIR_BLKDEVICE = $(LIBUC_INC_DIR)/BLKDEVICE - -LIBUC_INC_DIR_CORE_CMD = -I $(LIBUC_INC_DIR_CORE) -LIBUC_INC_DIR_UCSTRINGS_CMD = -I $(LIBUC_INC_DIR_UCSTRINGS) -LIBUC_INC_DIR_UART_CMD = -I $(LIBUC_INC_DIR_UART) -LIBUC_INC_DIR_SPI_CMD = -I $(LIBUC_INC_DIR_SPI) -LIBUC_INC_DIR_SSP_CMD = -I $(LIBUC_INC_DIR_SSP) -LIBUC_INC_DIR_IIC_CMD = -I $(LIBUC_INC_DIR_IIC) -LIBUC_INC_DIR_ADC_CMD = -I $(LIBUC_INC_DIR_ADC) -LIBUC_INC_DIR_24LC0X_CMD = -I $(LIBUC_INC_DIR_24LC0X) -LIBUC_INC_DIR_SDCARD_CMD = -I $(LIBUC_INC_DIR_SDCARD) -LIBUC_INC_DIR_VS10XX_CMD = -I $(LIBUC_INC_DIR_VS10XX) -LIBUC_INC_DIR_BLKDEVICE_CMD = -I $(LIBUC_INC_DIR_BLKDEVICE) #--------------------------------------------------------------------------------- # BOARD SUPORT PACKAGES @@ -146,9 +88,23 @@ LIBUC_BSP_INC = -I $(LIBUC_BSP_INC_DIR)/ #--------------------------------------------------------------------------------- # DEVICE SPECIAL FILES #--------------------------------------------------------------------------------- -LINKER_SCRIPT = $(ARCHFOLDER)/LPC2103_ram.ld -APPSOURCES += $(ARCHFOLDER)/ramstartup-1.S -LPC21XX_INCDIR=$(ARCHFOLDER) +LINKER_SCRIPT = $(ARCHFOLDER)/LPC2378-ROM.ld +DEVSOURCES += +DEVSOURCESND = $(notdir $(DEVSOURCES)) +DEVOBJECTFILES += $(DEVSOURCESND:.c=.o) +DEVOBJECTFILES := $(addprefix $(OBJDIR)/,$(DEVOBJECTFILES)) +OBJECTFILES += $(DEVOBJECTFILES) + +ASMDEVSOURCES += $(ARCHFOLDER)/crt0.S +ASMDEVSOURCESND = $(notdir $(ASMDEVSOURCES)) +ASMDEVOBJECTFILES += $(ASMDEVSOURCESND:.S=.o) +ASMDEVOBJECTFILES := $(addprefix $(OBJDIR)/,$(ASMDEVOBJECTFILES)) +ASMOBJECTFILES += $(ASMDEVOBJECTFILES) + +#RUN_MODE=ROM_RUN +#LIBUC_CFLAGS += -D$(RUN_MODE) + +LPC23XX_INCDIR=$(ARCHFOLDER) #--------------------------------------------------------------------------------- @@ -156,39 +112,56 @@ LPC21XX_INCDIR=$(ARCHFOLDER) #--------------------------------------------------------------------------------- all: - @echo "lpc21XX-arm-noabi-gcc rules" + @echo "lpc23XX-arm-noabi-gcc rules" -bin: $(TARGET).bin $(TARGET).hex +bin: $(ASMDEVSOURCESND) $(DEVSOURCESND) $(BINDIR)/$(TARGET).bin $(BINDIR)/$(TARGET).hex @echo "compile bin" - +$(DEVSOURCESND): $(DEVSOURCES) + cp -f $(DEVSOURCES) ./ + +$(ASMDEVSOURCESND): $(ASMDEVSOURCES) + cp -f $(ASMDEVSOURCES) ./ -lib: $(TARGET).a +lib: $(TARGETINSTALLPATH)/$(TARGET).a @echo "compile lib" %.a: $(OBJECTFILES) mkdir -p $(TARGETINSTALLPATH) mkdir -p $(HEADERSINSTALLPATH) - $(LIBUC_AR) rcs $(TARGETINSTALLPATH)/$@ $(OBJECTFILES) + $(LIBUC_AR) rcs $@ $(OBJECTFILES) #$(LIBUC_AR) rcs $(TARGETINSTALLPATH)/$@ $(OBJECTFILES) cp -f $(HEADERS) $(HEADERSINSTALLPATH)/ -%.o: %.S - $(LIBUC_CC) -O3 -c -o $@ $< $(LIBUC_CFLAGS) + +#%.o: %.c +# $(LIBUC_CC) -O3 -I $(LPC17XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -MM $< -MF $*.d -MP +# $(LIBUC_CC) -O3 -I $(LPC17XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -c $(LIBUC_CFLAGS) $< -o $@ -%.o: %.c - $(LIBUC_CC) -O3 -I $(LPC21XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -MM $< -MF $*.d -MP - $(LIBUC_CC) -O3 -I $(LPC21XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -c $(LIBUC_CFLAGS) $< -o $@ +$(OBJECTFILES) : $(OBJDIR)/%.o : %.c $(INC_LIBS_DEPS) $(HEADERS) + mkdir -p $(OBJDIR) + $(LIBUC_CC) -O3 -I $(LPC23XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -MM $< -MF $*.d -MP + $(LIBUC_CC) -O3 -I $(LPC23XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -c $(LIBUC_CFLAGS) $< -o $@ + -%.elf: $(LINKER_SCRIPT) $(OBJECTFILES) - $(LIBUC_CC) -O3 -nostartfiles -T $^ -o $@ -static $(LIBUC_BSP) $(LIBUC_LIBRARIES) +$(ASMOBJECTFILES) : $(OBJDIR)/%.o : %.S $(INC_LIBS_DEPS) $(HEADERS) + mkdir -p $(OBJDIR) + $(LIBUC_CC) -O3 -I $(LPC23XX_INCDIR) $(LIBUC_INCLUDES) $(LIBUC_BSP_INC) -c $(LIBUC_CFLAGS) $< -o $@ + + +%.elf: $(LINKER_SCRIPT) $(ASMOBJECTFILES) $(OBJECTFILES) + mkdir -p $(BINDIR) + $(LIBUC_CC) $(LIBUC_LDFLAGS) $(LIBUC_CFLAGS) -T $^ -o $@ $(LIBUC_BSP) $(LIBUC_LIBRARIES) $(LIBUC_OBJDUMP) $(LIBUC_ODFLAGS) $@ > $(@:.elf=.dump) $(LIBUC_SIZE) $@ - -%.bin: %.elf + + + +%.bin: %.elf $(BIN_LIBS_DEPS) $(LIBUC_OBJCOPY) $(LIBUC_CPFLAGS) -O binary $< $*.bin - + @echo "BIN_LIBS_DEPS" + @echo $(BIN_LIBS_DEPS) %.hex: %.elf $(LIBUC_OBJCOPY) $(LIBUC_CPFLAGS) -O ihex $< $*.hex @@ -196,6 +169,13 @@ lib: $(TARGET).a clean: rm -f *.o *.d *.bin *.hex *.dump *.map *.a + rm -f $(OBJECTFILES) + rm -f $(BINDIR)/*.bin + rm -f $(BINDIR)/*.hex + rm -f $(BINDIR)/*.dump + rm -f $(BINDIR)/*.map + rm -f $(BINDIR)/*.a + rm -f $(DEVSOURCESND) distclean: rm -f $(TARGETINSTALLPATH)/*.bin @@ -209,3 +189,10 @@ distclean: + + + + + + +