diff --git a/Makefile b/Makefile index 277dd02..6c8092c 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ SUBDIRS := miosix ## List here your source files (both .s, .c and .cpp) ## SRC := \ -miosix/testsuite/testsuite.cpp +main.cpp ## ## List here additional static libraries with relative path diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp index 26dffda..c0c454f 100644 --- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp +++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/disk.cpp @@ -33,8 +33,6 @@ #include "kernel/kernel.h" #include #include -#include -#include //FIXME: remove //Note: enabling debugging might cause deadlock when using sleep() or reboot() //The bug won't be fixed because debugging is only useful for driver development @@ -42,8 +40,8 @@ //#define DBG iprintf #define DBG(x,...) ; ///\internal Debug macro, for errors only -#define DBGERR iprintf -//#define DBGERR(x,...) ; +//#define DBGERR iprintf +#define DBGERR(x,...) ; /** * \internal @@ -121,8 +119,8 @@ void __attribute__((used)) SDIOirqImpl() * work at this voltage. Range *must* be within 28..36 * Example 33=3.3v */ -const unsigned char VOLTAGE=33; -const unsigned int VOLTAGE_MASK=1<<(VOLTAGE-13); //See OCR register in SD spec +static const unsigned char VOLTAGE=33; +static const unsigned int VOLTAGE_MASK=1<<(VOLTAGE-13); //See OCR reg in SD spec /** * \internal @@ -148,134 +146,6 @@ typedef Gpio sdD3; typedef Gpio sdCLK; typedef Gpio sdCMD; -// -// Class BufferConverter -// - -/** - * \internal - * Convert a single buffer of *fixed* and predetermined size to and from - * word-aligned. To do so, if the buffer is already word aligned a cast is made, - * otherwise a new buffer is allocated. - * Note that this class allocates at most ONE buffer at any given time. - * Therefore any call to toWordAligned(), toWordAlignedWithoutCopy(), - * toOriginalBuffer() or deallocateBuffer() invalidates the buffer previousy - * returned by toWordAligned() and toWordAlignedWithoutCopy() - */ -class BufferConverter -{ -public: - /** - * \internal - * The buffer will be of this size only. - */ - static const int BUFFER_SIZE=512; - - /** - * \internal - * \return true if the pointer is word aligned - */ - static bool isWordAligned(const unsigned char *x) - { - return (reinterpret_cast(x) & 0x3)==0; - } - - /** - * \internal - * Convert from a constunsigned char* buffer of size BUFFER_SIZE to a - * const unsigned int* word aligned buffer. - * If the original buffer is already word aligned it only does a cast, - * otherwise it copies the data on the original buffer to a word aligned - * buffer. Useful if subseqent code will read from the buffer. - * \param a buffer of size BUFFER_SIZE. Can be word aligned or not. - * \return a word aligned buffer with the same data of the given buffer - */ - static const unsigned int *toWordAligned(const unsigned char *buffer); - - /** - * \internal - * Convert from an unsigned char* buffer of size BUFFER_SIZE to an - * unsigned int* word aligned buffer. - * If the original buffer is already word aligned it only does a cast, - * otherwise it returns a new buffer which *does not* contain the data - * on the original buffer. Useful if subseqent code will write to the - * buffer. To move the written data to the original buffer, use - * toOriginalBuffer() - * \param a buffer of size BUFFER_SIZE. Can be word aligned or not. - * \return a word aligned buffer with undefined content. - */ - static unsigned int *toWordAlignedWithoutCopy(unsigned char *buffer); - - /** - * \internal - * Convert the buffer got through toWordAlignedWithoutCopy() to the - * original buffer. If the original buffer was word aligned, nothing - * happens, otherwise a memcpy is done. - * Note that this function does not work on buffers got through - * toWordAligned(). - */ - static void toOriginalBuffer(); - - /** - * \internal - * Can be called to deallocate the buffer - */ - static void deallocateBuffer(); - -private: - static unsigned char *originalBuffer; - static unsigned int *wordAlignedBuffer; -}; - -const unsigned int *BufferConverter::toWordAligned(const unsigned char *buffer) -{ - originalBuffer=0; //Tell toOriginalBuffer() that there's nothing to do - if(isWordAligned(buffer)) - { - return reinterpret_cast(buffer); - } else { - if(wordAlignedBuffer==0) - wordAlignedBuffer=new unsigned int[BUFFER_SIZE/sizeof(unsigned int)]; - std::memcpy(wordAlignedBuffer,buffer,BUFFER_SIZE); - return wordAlignedBuffer; - } -} - -unsigned int *BufferConverter::toWordAlignedWithoutCopy( - unsigned char *buffer) -{ - if(isWordAligned(buffer)) - { - originalBuffer=0; //Tell toOriginalBuffer() that there's nothing to do - return reinterpret_cast(buffer); - } else { - originalBuffer=buffer; //Save original pointer for toOriginalBuffer() - if(wordAlignedBuffer==0) - wordAlignedBuffer=new unsigned int[BUFFER_SIZE/sizeof(unsigned int)]; - return wordAlignedBuffer; - } -} - -void BufferConverter::toOriginalBuffer() -{ - if(originalBuffer==0) return; - std::memcpy(originalBuffer,wordAlignedBuffer,BUFFER_SIZE); - originalBuffer=0; -} - -void BufferConverter::deallocateBuffer() -{ - originalBuffer=0; //Invalidate also original buffer - if(wordAlignedBuffer!=0) - { - delete[] wordAlignedBuffer; - wordAlignedBuffer=0; - } -} - -unsigned char *BufferConverter::originalBuffer=0; -unsigned int *BufferConverter::wordAlignedBuffer=0; - // // Class CmdResult // @@ -515,26 +385,7 @@ class Command * \param arg the 32 bit argument to the command * \return a CmdResult object */ - static CmdResult send(CommandType cmd, unsigned int arg) - { - if(static_cast(cmd) & 0x80) - { - DBG("ACMD%d\n",static_cast(cmd) & 0x3f); - } else { - DBG("CMD%d\n",static_cast(cmd) & 0x3f); - } - return IRQsend(cmd,arg); - } - - /** - * \internal - * Send a command. Can be called with interrupts disabled as it does not - * print any debug information. - * \param cmd command index (CMD0..CMD63) or ACMDxx command - * \param arg the 32 bit argument to the command - * \return a CmdResult object - */ - static CmdResult IRQsend(CommandType cmd, unsigned int arg); + static CmdResult send(CommandType cmd, unsigned int arg); /** * \internal @@ -553,19 +404,20 @@ class Command static unsigned short rca;///<\internal Card's relative address }; -CmdResult Command::IRQsend(CommandType cmd, unsigned int arg) +CmdResult Command::send(CommandType cmd, unsigned int arg) { unsigned char cc=static_cast(cmd); //Handle ACMDxx as CMD55, CMDxx if(cc & 0x80) { - CmdResult r=IRQsend(CMD55,(static_cast(rca))<<16); - if(r.IRQvalidateR1Response()==false) + DBG("ACMD%d\n",cc & 0x3f); + CmdResult r=send(CMD55,(static_cast(rca))<<16); + if(r.validateR1Response()==false) return CmdResult(cc & 0x3f,CmdResult::ACMDFail); //Bit 5 @ 1 = next command will be interpreted as ACMD if((r.getResponse() & (1<<5))==0) return CmdResult(cc & 0x3f,CmdResult::ACMDFail); - } + } else DBG("CMD%d\n",cc & 0x3f); //Send command cc &= 0x3f; @@ -616,103 +468,16 @@ CmdResult Command::IRQsend(CommandType cmd, unsigned int arg) unsigned short Command::rca=0; -// -// Class DataResult -// - -/** - * \internal - * Contains the result of sending/receiving a data block - */ -class DataResult -{ -public: - - /** - * \internal - * Possible outcomes of sending or receiving data - */ - enum Error - { - Ok=0, - Timeout, - CRCFail, - RXOverrun, - TXUnderrun, - StartBitFail - }; - - /** - * \internal - * Default constructor - */ - DataResult(): error(Ok) {} - - /** - * \internal - * Constructor, set the result. - * \param error error type - */ - DataResult(Error error): error(error) {} - - /** - * \internal - * \return the error flags - */ - Error getError() { return error; } - - /** - * \internal - * Checks if errors occurred while sending/receiving data. - * \return true if no errors, false otherwise - */ - bool validateError(); - -private: - Error error; -}; - - -bool DataResult::validateError() -{ - switch(error) - { - case Ok: - return true; - case Timeout: - DBGERR("Data Timeout\n"); - break; - case CRCFail: - DBGERR("Data CRC Fail\n"); - break; - case RXOverrun: - DBGERR("Data overrun\n"); - break; - case TXUnderrun: - DBGERR("Data underrun\n"); - break; - case StartBitFail: - DBGERR("Data start bit Fail\n"); - break; - } - return false; -} - // // Class ClockController // /** * \internal - * This class controls the clock speed of the SDIO peripheral. The SDIO - * peripheral, when used in polled mode, requires two timing critical pieces of - * code: the one to send and the one to receive a data block. This because - * the peripheral has a 128 byte fifo while the block size is 512 byte, and - * if fifo underrun/overrun occurs the peripheral does not pause communcation, - * instead it simply aborts the data transfer. Since the speed of the code to - * read/write a data block depends on too many factors, such as compiler - * optimizations, code running from internal flash or external ram, and the - * cpu clock speed, a dynamic clocking approach was chosen. + * This class controls the clock speed of the SDIO peripheral. It originated + * from a previous version of this driver, where the SDIO was used in polled + * mode instead of DMA mode, but has been retained to improve the robustness + * of the driver. */ class ClockController { @@ -734,12 +499,9 @@ class ClockController /** * \internal - * Automatically select the data speed. - * Since the maximum speed depends on many factors, such as code running in - * internal or external RAM, compiler optimizations etc. this routine - * selects the highest sustainable data transfer speed. - * This is done by binary search until the highest clock speed that causes - * no errors is found. + * Automatically select the data speed. This routine selects the highest + * sustainable data transfer speed. This is done by binary search until + * the highest clock speed that causes no errors is found. * This function as a side effect enables 4bit bus width, and clock * powersave. */ @@ -747,7 +509,7 @@ class ClockController /** * \internal - * Since clock speed is set dynamically by bynary search at runtime, a + * Since clock speed is set dynamically by binary search at runtime, a * corner case might be that of a clock speed which results in unreliable * data transfer, that sometimes succeeds, and sometimes fail. * For maximum robustness, this function is provided to reduce the clock @@ -756,10 +518,9 @@ class ClockController * clock issues, this function can be called only MAX_ALLOWED_REDUCTIONS * times after clock calibration, subsequent calls will fail. This will * avoid other issues causing an ever decreasing clock speed. - * Can be called with interrupts disabled. * \return true on success, false on failure */ - static bool IRQreduceClockSpeed(); + static bool reduceClockSpeed(); /** * \internal @@ -776,12 +537,19 @@ class ClockController static const unsigned int CLOCK_400KHz=118; //48MHz/(118+2)=400KHz static const unsigned int CLOCK_MAX=0; //48MHz/(0+2) =24MHz + #ifndef _BOARD_STM3220G_EVAL ///\internal Clock enabled, bus width 4bit, clock powersave enabled. static const unsigned int CLKCR_FLAGS=SDIO_CLKCR_CLKEN | SDIO_CLKCR_WIDBUS_0 | SDIO_CLKCR_PWRSAV; + #else //_BOARD_STM3220G_EVAL + //Quirk: in the stm3220g-eval the serial port shares some pin with the + //SDIO data bus, so use 1 bit mode, even if it's slower + ///\internal Clock enabled, bus width 1bit, clock powersave enabled. + static const unsigned int CLKCR_FLAGS=SDIO_CLKCR_CLKEN | SDIO_CLKCR_PWRSAV; + #endif //_BOARD_STM3220G_EVAL ///\internal Maximum number of calls to IRQreduceClockSpeed() allowed - static const unsigned char MAX_ALLOWED_REDUCTIONS=5; + static const unsigned char MAX_ALLOWED_REDUCTIONS=1; ///\internl value returned by getRetryCount() while *not* calibrating clock. static const unsigned char MAX_RETRY=3; @@ -789,6 +557,7 @@ class ClockController ///\internal Used to allow only one call to reduceClockSpeed() static unsigned char clockReductionAvailable; + ///\internal value returned by getRetryCount() static unsigned char retries; }; @@ -828,9 +597,10 @@ void ClockController::calibrateClockSpeed() retries=MAX_RETRY; } -bool ClockController::IRQreduceClockSpeed() +bool ClockController::reduceClockSpeed() { - //Ensure this function can be called only twice per calibration + DBGERR("clok speed reduction requested\n"); + //Ensure this function can be called only a few times if(clockReductionAvailable==0) return false; clockReductionAvailable--; @@ -859,254 +629,27 @@ unsigned char ClockController::retries=ClockController::MAX_RETRY; * Can be called independently of the card being selected. * \return true on success, false on failure */ -bool waitForCardReady() +static bool waitForCardReady() { - for(int i=0;i<300;i++) //Timeout 1.5 second + const int timeout=1500; //Timeout 1.5 second + const int sleepTime=2; + for(int i=0;iDLEN and must match the size parameter given to this - * function. - * \param buffer buffer where to store received data. Its size must be >=size - * \param buffer size, which *must* be multiple of 8 words (32bytes) - * Note that the size parameter must be expressed in word (4bytes), while - * the value in SDIO->DLEN is expressed in bytes. - * \return a DataResult object - */ -static DataResult IRQreceiveDataBlock(unsigned int *buffer, unsigned int size) -{ - // A note on speed. - // Due to the auto calibration of SDIO clock speed being done with - // IRQreceiveDataBlock(), the speed of this function must be comparable - // with the speed of IRQsendDataBlock(), otherwise IRQsendDataBlock() - // will fail because of data underrun. - const unsigned int *bufend=buffer+size; - unsigned int status; - for(;;) - { - status=SDIO->STA; - if(status & (SDIO_STA_RXOVERR | SDIO_STA_DCRCFAIL | - SDIO_STA_DTIMEOUT | SDIO_STA_STBITERR | SDIO_STA_DBCKEND)) break; - if((status & SDIO_STA_RXFIFOHF) && (buffer!=bufend)) - { - //Read 8 words from the fifo, loop entirely unrolled for speed - *buffer=SDIO->FIFO; buffer++; - *buffer=SDIO->FIFO; buffer++; - *buffer=SDIO->FIFO; buffer++; - *buffer=SDIO->FIFO; buffer++; - *buffer=SDIO->FIFO; buffer++; - *buffer=SDIO->FIFO; buffer++; - *buffer=SDIO->FIFO; buffer++; - *buffer=SDIO->FIFO; buffer++; - } - } - SDIO->ICR=0x7ff;//Clear flags - if(status & SDIO_STA_RXOVERR) return DataResult(DataResult::RXOverrun); - if(status & SDIO_STA_DCRCFAIL) return DataResult(DataResult::CRCFail); - if(status & SDIO_STA_DTIMEOUT) return DataResult(DataResult::Timeout); - if(status & SDIO_STA_STBITERR) return DataResult(DataResult::StartBitFail); - //Read eventual data left in the FIFO - for(;;) - { - if((SDIO->STA & SDIO_STA_RXDAVL)==0) break; - *buffer=SDIO->FIFO; buffer++; - } - return DataResult(DataResult::Ok); -} - -/** - * \internal - * Send a data block. The end of the data block must be told to the SDIO - * peripheral in SDIO->DLEN and must match the size parameter given to this - * function. - * \param buffer buffer where to store received data. Its size must be >=size - * \param buffer size, which *must* be multiple of 8 words (32bytes). - * Note that the size parameter must be expressed in word (4bytes), while - * the value in SDIO->DLEN is expressed in bytes. - * \return a DataResult object - */ -static DataResult IRQsendDataBlock(const unsigned int *buffer, unsigned int size) -{ - // A note on speed. - // Due to the auto calibration of SDIO clock speed being done with - // IRQreceiveDataBlock(), the speed of this function must be comparable - // with the speed of IRQreceiveDataBlock(), otherwise this function - // will fail because of data underrun. - const unsigned int *bufend=buffer+size; - unsigned int status; - for(;;) - { - status=SDIO->STA; - if(status & (SDIO_STA_TXUNDERR | SDIO_STA_DCRCFAIL | - SDIO_STA_DTIMEOUT | SDIO_STA_STBITERR | SDIO_STA_DBCKEND)) break; - if((status & SDIO_STA_TXFIFOHE) && (buffer!=bufend)) - { - //Write 8 words to the fifo, loop entirely unrolled for speed - SDIO->FIFO=*buffer; buffer++; - SDIO->FIFO=*buffer; buffer++; - SDIO->FIFO=*buffer; buffer++; - SDIO->FIFO=*buffer; buffer++; - SDIO->FIFO=*buffer; buffer++; - SDIO->FIFO=*buffer; buffer++; - SDIO->FIFO=*buffer; buffer++; - SDIO->FIFO=*buffer; buffer++; - } - } - SDIO->ICR=0x7ff;//Clear flags - if(status & SDIO_STA_TXUNDERR) return DataResult(DataResult::TXUnderrun); - if(status & SDIO_STA_DCRCFAIL) return DataResult(DataResult::CRCFail); - if(status & SDIO_STA_DTIMEOUT) return DataResult(DataResult::Timeout); - if(status & SDIO_STA_STBITERR) return DataResult(DataResult::StartBitFail); - return DataResult(DataResult::Ok); -} - -/** - * \internal - * Read a single block of 512 bytes from an SD/MMC card. - * Card must be selected prior to caling this function. - * \param buffer, a buffer whose size is >=512 bytes - * \param lba logical block address of the block to read. - */ -static bool singleBlockRead(unsigned char *buffer, unsigned int lba) -{ - if(cardType!=SDHC) lba*=512; // Convert to byte address if not SDHC - - if(waitForCardReady()==false) return false; - - // Single block read - unsigned int* newBuf=BufferConverter::toWordAlignedWithoutCopy(buffer); - CmdResult cr; - DataResult dr; - bool failed=true; - for(;;) - { - // Since we read with polling, a context switch or interrupt here - // would cause a fifo overrun, so we disable interrupts. - FastInterruptDisableLock dLock; - - SDIO->DLEN=512; - //Block size 512 bytes, block data xfer, from card to controller - SDIO->DCTRL=(9<<4) | SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; - - cr=Command::IRQsend(Command::CMD17,lba); - if(cr.IRQvalidateR1Response()) - { - dr=IRQreceiveDataBlock(newBuf,512/sizeof(unsigned int)); - SDIO->DCTRL=0; //Disable data path state machine - - //If failed because too slow check if it is possible to reduce speed - if(dr.getError()==DataResult::RXOverrun) - { - if(ClockController::IRQreduceClockSpeed()) - { - //Disabling interrupts for too long is bad - FastInterruptEnableLock eLock(dLock); - //After an error during data xfer the card might be a little - //confused. So send STOP_TRANSMISSION command to reassure it - cr=Command::send(Command::CMD12,0); - if(cr.validateR1Response()) continue; - } - } - - if(dr.getError()==DataResult::Ok) failed=false; - } - break; - } - if(failed) - { - cr.validateR1Response(); - dr.validateError(); - //After an error during data xfer the card might be a little - //confused. So send STOP_TRANSMISSION command to reassure it - cr=Command::send(Command::CMD12,0); - cr.validateR1Response(); - return false; - } - BufferConverter::toOriginalBuffer(); - return true; -} - -/** - * \internal - * Write a single block of 512 bytes to an SD/MMC card - * Card must be selected prior to caling this function. - * \param buffer, a buffer whose size is >=512 bytes - * \param lba logical block address of the block to write. - */ -static bool singleBlockWrite(const unsigned char *buffer, unsigned int lba) -{ - if(cardType!=SDHC) lba*=512; // Convert to byte address if not SDHC - - if(waitForCardReady()==false) return false; - - // Single block write - const unsigned int* newBuf=BufferConverter::toWordAligned(buffer); - bool failed=true; - CmdResult cr; - DataResult dr; - for(;;) - { - // Since we write with polling, a context switch or interrupt here - // would cause a fifo overrun, so we disable interrupts. - FastInterruptDisableLock dLock; - - cr=Command::IRQsend(Command::CMD24,lba); - if(cr.IRQvalidateR1Response()) - { - SDIO->DLEN=512; - //Block size 512 bytes, block data xfer, from controller to card - SDIO->DCTRL=(9<<4) | SDIO_DCTRL_DTEN; - - dr=IRQsendDataBlock(newBuf,512/sizeof(unsigned int)); - SDIO->DCTRL=0; //Disable data path state machine - - //If failed because too slow check if it is possible to reduce speed - if(dr.getError()==DataResult::TXUnderrun) - { - if(ClockController::IRQreduceClockSpeed()) - { - //Disabling interrupts for too long is bad - FastInterruptEnableLock eLock(dLock); - //After an error during data xfer the card might be a little - //confused. So send STOP_TRANSMISSION command to reassure it - cr=Command::send(Command::CMD12,0); - if(cr.validateR1Response()) continue; - } - } - - if(dr.getError()==DataResult::Ok) failed=false; - } - break; - } - if(failed) - { - cr.validateR1Response(); - dr.validateError(); - //After an error during data xfer the card might be a little - //confused. So send STOP_TRANSMISSION command to reassure it - cr=Command::send(Command::CMD12,0); - cr.validateR1Response(); - return false; - } - return true; -} - /** * \internal * Prints the errors that may occur during a DMA transfer */ -void displayBlockTransferError() +static void displayBlockTransferError() { DBGERR("Block transfer error\n"); if(dmaFlags & DMA_LISR_TEIF3) DBGERR("* DMA Transfer error\n"); @@ -1126,7 +669,7 @@ void displayBlockTransferError() * memory transfer size based on buffer alignment * \return the best DMA transfer size for a given buffer alignment */ -unsigned int dmaTransferCommonSetup(const unsigned char *buffer) +static unsigned int dmaTransferCommonSetup(const unsigned char *buffer) { //Clear both SDIO and DMA interrupt flags SDIO->ICR=0x7ff; @@ -1158,9 +701,14 @@ unsigned int dmaTransferCommonSetup(const unsigned char *buffer) * Due to hardware limitations must be between 0 and 32767. * \param lba logical block address of the first block to read. */ -static bool multipleBlockRead(unsigned char *buffer, int nblk, unsigned int lba) +static bool multipleBlockRead(unsigned char *buffer, unsigned int nblk, + unsigned int lba) { - if(nblk<0 || nblk>32767) return false; + if(nblk>32767) + { + DBGERR("nblk too large\n"); + return false; + } if(waitForCardReady()==false) return false; if(cardType!=SDHC) lba*=512; // Convert to byte address if not SDHC @@ -1224,7 +772,7 @@ static bool multipleBlockRead(unsigned char *buffer, int nblk, unsigned int lba) if(transferError || cr.validateR1Response()==false) { displayBlockTransferError(); -// ClockController::IRQreduceClockSpeed(); + ClockController::reduceClockSpeed(); return false; } return true; @@ -1239,10 +787,14 @@ static bool multipleBlockRead(unsigned char *buffer, int nblk, unsigned int lba) * Due to hardware limitations must be between 0 and 32767. * \param lba logical block address of the first block to write. */ -static bool multipleBlockWrite(const unsigned char *buffer, int nblk, +static bool multipleBlockWrite(const unsigned char *buffer, unsigned int nblk, unsigned int lba) { - if(nblk<0 || nblk>32767) return false; + if(nblk>32767) + { + DBGERR("nblk too large\n"); + return false; + } if(waitForCardReady()==false) return false; if(cardType!=SDHC) lba*=512; // Convert to byte address if not SDHC @@ -1261,8 +813,10 @@ static bool multipleBlockWrite(const unsigned char *buffer, int nblk, DMA2_Stream3->PAR=reinterpret_cast(&SDIO->FIFO); DMA2_Stream3->M0AR=reinterpret_cast(buffer); //Note: DMA2_Stream3->NDTR is don't care in peripheral flow control mode - DMA2_Stream3->FCR=/*DMA_SxFCR_FEIE |*/ //Interrupt on fifo error - DMA_SxFCR_DMDIS | //Fifo enabled + //Quirk: not enabling DMA_SxFCR_FEIE because the SDIO seems to generate + //a spurious fifo error. The code was tested and the transfer completes + //successfully even in the presence of this fifo error + DMA2_Stream3->FCR=DMA_SxFCR_DMDIS | //Fifo enabled DMA_SxFCR_FTH_1 | //Take action if fifo full DMA_SxFCR_FTH_0; DMA2_Stream3->CR=DMA_SxCR_CHSEL_2 | //Channel 4 (SDIO) @@ -1307,7 +861,7 @@ static bool multipleBlockWrite(const unsigned char *buffer, int nblk, if(transferError || cr.validateR1Response()==false) { displayBlockTransferError(); -// ClockController::IRQreduceClockSpeed(); + ClockController::reduceClockSpeed(); return false; } return true; @@ -1356,47 +910,6 @@ class CardSelector bool success; }; -void fixmeTestFs() -{ - puts("----------"); - const unsigned int sec=3250585; - unsigned char *b0=new unsigned char[4096]; - unsigned char *b1=new unsigned char[4096]; - unsigned char *b2=new unsigned char[4096]; - memset(b1,'a',4096); - memset(b2,'b',4096); - int al=2; - int nb=7; - srand(getTick()); - for(int i=0;i<512*nb;i++) b0[i+al]=rand() & 0xff; - - { - CardSelector selector; - if(selector.succeded()==false) puts("card select failed!"); - if(multipleBlockWrite(b0+al,nb,sec)==false) puts("Fsbw failed!"); - for(int i=0;iAPB2ENR |= RCC_APB2ENR_SDIOEN; sdD0::mode(Mode::ALTERNATE); sdD0::alternateFunction(12); + #ifndef _BOARD_STM3220G_EVAL + //Quirk: in the stm3220g-eval the serial port shares some pin with the + //SDIO data bus, so use 1 bit mode, even if it's slower sdD1::mode(Mode::ALTERNATE); sdD1::alternateFunction(12); sdD2::mode(Mode::ALTERNATE); sdD2::alternateFunction(12); sdD3::mode(Mode::ALTERNATE); sdD3::alternateFunction(12); + #endif //_BOARD_STM3220G_EVAL sdCLK::mode(Mode::ALTERNATE); sdCLK::alternateFunction(12); sdCMD::mode(Mode::ALTERNATE); @@ -1436,8 +953,8 @@ static void initSDIOPeripheral() SDIO->CMD=0; SDIO->DCTRL=0; SDIO->ICR=0xc007ff; - SDIO->POWER=SDIO_POWER_PWRCTRL_1 | SDIO_POWER_PWRCTRL_0; //Power on state SDIO->DTIMER=1048576; + SDIO->POWER=SDIO_POWER_PWRCTRL_1 | SDIO_POWER_PWRCTRL_0; //Power on state //This delay is particularly important: when setting the POWER register a //glitch on the CMD pin happens. This glitch has a fast fall time and a slow //rise time resembling an RC charge with a ~6us rise time. If the clock is @@ -1600,8 +1117,12 @@ void Disk::init() return; } + #ifndef _BOARD_STM3220G_EVAL + //Quirk: in the stm3220g-eval the serial port shares some pin with the + //SDIO data bus, so use 1 bit mode, even if it's slower r=Command::send(Command::ACMD6,2); //Set 4 bit bus width if(r.validateR1Response()==false) return; + #endif //_BOARD_STM3220G_EVAL if(cardType!=SDHC) { @@ -1622,29 +1143,11 @@ bool Disk::read(unsigned char *buffer, unsigned int lba, unsigned char nSectors) { DBG("Disk::read(): nSectors=%d\n",nSectors); - if(!BufferConverter::isWordAligned(buffer)) DBG("Buffer misaligned\n"); - for(int i=0;i0) DBGERR("Read: required %d retries\n",i); return true; } @@ -1655,29 +1158,11 @@ bool Disk::write(const unsigned char *buffer, unsigned int lba, unsigned char nSectors) { DBG("Disk::write(): nSectors=%d\n",nSectors); - if(!BufferConverter::isWordAligned(buffer)) DBG("Buffer misaligned\n"); - for(int i=0;i0) DBGERR("Write: required %d retries\n",i); return true; } diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc index 0675fb5..7dddd53 100644 --- a/miosix/config/Makefile.inc +++ b/miosix/config/Makefile.inc @@ -13,14 +13,14 @@ ## architecture ## #OPT_BOARD := lpc2138_miosix_board -#OPT_BOARD := stm32f103ze_stm3210e-eval +OPT_BOARD := stm32f103ze_stm3210e-eval #OPT_BOARD := stm32f103ve_mp3v2 #OPT_BOARD := stm32f100rb_stm32vldiscovery #OPT_BOARD := stm32f103ve_strive_mini #OPT_BOARD := stm32f103ze_redbull_v2 #OPT_BOARD := stm32f407vg_stm32f4discovery #OPT_BOARD := stm32f207ig_stm3220g-eval -OPT_BOARD := stm32f207zg_ethboard_v2 +#OPT_BOARD := stm32f207zg_ethboard_v2 #OPT_BOARD := stm32f207ze_als_camboard #OPT_BOARD := stm32l151_als_mainboard #OPT_BOARD := stm32f407vg_bitsboard diff --git a/miosix/doc/textdoc/Changelog.txt b/miosix/doc/textdoc/Changelog.txt index 50314c7..58b7e33 100644 --- a/miosix/doc/textdoc/Changelog.txt +++ b/miosix/doc/textdoc/Changelog.txt @@ -1,5 +1,6 @@ Changelog for Miosix np embedded OS +- Actually, monitor_soft_reset_halt seems to work in JTAG mode but not with SWD - Changed references to "monitor soft_reset_halt" into "monitor reset halt" as openocd changed in version 0.6.1 - Added scripts to build the new GCC 4.7.2 diff --git a/miosix/doc/textdoc/stm32-bootloader.txt b/miosix/doc/textdoc/stm32-bootloader.txt index 83d6f26..93b3f9d 100644 --- a/miosix/doc/textdoc/stm32-bootloader.txt +++ b/miosix/doc/textdoc/stm32-bootloader.txt @@ -82,7 +82,7 @@ and in another shell type: arm-eabi-gdb main.elf target remote :3333 -monitor reset halt +monitor soft_reset_halt load c diff --git a/miosix/temp/feedforward_profiling/gdb_init.script b/miosix/temp/feedforward_profiling/gdb_init.script index e6f416b..b4589a2 100644 --- a/miosix/temp/feedforward_profiling/gdb_init.script +++ b/miosix/temp/feedforward_profiling/gdb_init.script @@ -4,7 +4,7 @@ target remote :3333 -monitor reset halt +monitor soft_reset_halt load # Breakpoint must be put on line that sets Tr to zero, diff --git a/miosix/testsuite/testsuite.cpp b/miosix/testsuite/testsuite.cpp index fc4f9fb..61dcfbe 100644 --- a/miosix/testsuite/testsuite.cpp +++ b/miosix/testsuite/testsuite.cpp @@ -106,10 +106,6 @@ static void benchmark_4(); static void exception_test(); #endif //__NO_EXCEPTIONS -namespace miosix { -void fixmeTestFs(); -} - //main(), calls all tests int main() { @@ -128,7 +124,6 @@ int main() } switch(c) { - case '0': fixmeTestFs(); break; case 't': //for(;;){ //Testing ledOn();