Go Down

Topic: Teensy 3.0 (Read 37 times) previous topic - next topic

fat16lib

#40
Oct 08, 2012, 03:45 pm Last Edit: Oct 08, 2012, 04:04 pm by fat16lib Reason: 1
Paul, I am doing a major redesign of SdFat to use better caching and faster SD commands so large writes/reads will be much faster.

I plan to support SPI and 4-bit SDIO on various Cortex M chips.  I also want to make SdFat RTOS friendly when using DMA.

I would love to have a better low level SPI library for each chip.

I need a way to restore the SPI speed and mode each time I access the SD.  I need single byte read and write for sending commands, receiving status, and polling for busy.

I need fast block read and write routines.  These could use a fifo or DMA.

I am ready to start testing with some prototype SPI functions I have done but for some reason my Teensy 3.0 has not arrived in California yet.

Edit:  I need the equivalent of these AVR functions.
Code: [Select]

//------------------------------------------------------------------------------
/**
* Initialize hardware SPI
* Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6]
*/
static void spiInit(uint8_t spiRate) {
 // See avr processor documentation
 SPCR = (1 << SPE) | (1 << MSTR) | (spiRate >> 1);
 SPSR = spiRate & 1 || spiRate == 6 ? 0 : 1 << SPI2X;
}
//------------------------------------------------------------------------------
/** SPI receive a byte */
static uint8_t spiRec() {
 SPDR = 0XFF;
 while (!(SPSR & (1 << SPIF)));
 return SPDR;
}
//------------------------------------------------------------------------------
/** SPI read data - only one call so force inline */
static inline __attribute__((always_inline))
 void spiRead(uint8_t* buf, uint16_t nbyte) {
 if (nbyte-- == 0) return;
 SPDR = 0XFF;
 for (uint16_t i = 0; i < nbyte; i++) {
   while (!(SPSR & (1 << SPIF)));
   uint8_t b = SPDR;
   SPDR = 0XFF;
   buf[i] = b;
 }
 while (!(SPSR & (1 << SPIF)));
 buf[nbyte] = SPDR;
}
//------------------------------------------------------------------------------
/** SPI send a byte */
static void spiSend(uint8_t b) {
 SPDR = b;
 while (!(SPSR & (1 << SPIF)));
}
//------------------------------------------------------------------------------
/** SPI send block - only one call so force inline */
static inline __attribute__((always_inline))
 void spiSendBlock(uint8_t token, const uint8_t* buf) {
 SPDR = token;
 for (uint16_t i = 0; i < 512; i++) {
   uint8_t b = buf[i];
   while (!(SPSR & (1 << SPIF)));
   SPDR = b;
 }
 while (!(SPSR & (1 << SPIF)));
}

Paul Stoffregen


Edit:  I need the equivalent of these AVR functions.


I can do those, using the fifo for good speed.

Is there a version of your library which already uses these?  Or some test code that calls them to do something simple, like read and print the MBR or Volume ID sector?

I need some sort of test code that I can compile and run.

fat16lib

This beta of SdFat uses the above functions: SdFatBeta20120825.zip http://code.google.com/p/beta-lib/downloads/list.

The functions are at the top of Sd2Card.cpp

It also has the following function to initialize AVR SPI pins:
Code: [Select]

/**
* initialize SPI pins
*/
static void spiBegin() {
  pinMode(MISO, INPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(SCK, OUTPUT);
  // SS must be in output mode even it is not chip select
  pinMode(SS, OUTPUT);
  // set SS high - may be chip select for another SPI device
#if SET_SPI_SS_HIGH
  digitalWrite(SS, HIGH);
#endif  // SET_SPI_SS_HIGH
}


This version of SdFat does not have the new stuff to speed up large reads and writes.  That involves changes to use multi-block SD commands.

Paul Stoffregen

I'm looking that the beta code now....

One minor but important point for compiling on 32 bit platforms is the use of packed structs.  By default, the compiler will align 32 bit types to 4 byte boundaries on 32 bit processors.  That's definitely not what you want in SdFatStructs.h.  It's necessary to add "__attribute__((packed))" to each struct definition, so the compiler packs the struct as intended.

For example.

Code: [Select]

struct masterBootRecord {
           /** Code Area for master boot program. */
  uint8_t  codeArea[440];
           /** Optional Windows NT disk signature. May contain boot code. */
  uint32_t diskSignature;
           /** Usually zero but may be more boot code. */
  uint16_t usuallyZero;
           /** Partition tables. */
  part_t   part[4];
           /** First MBR signature byte. Must be 0X55 */
  uint8_t  mbrSig0;
           /** Second MBR signature byte. Must be 0XAA */
  uint8_t  mbrSig1;
} __attribute__((packed));

Paul Stoffregen

The 32 bit compiler does not like many things in your iostream headers.  :-(

I'll work on this more later today or tomorrow.  For now, I need to focus on getting the rest of the kickstarter rewards shipped.

Go Up