Elastic Sheep

Because elasticdog was already taken

Elastic Sheep header image 2

Reading an SD card part 2: Teensy 2.0

January 14th, 2010 · 8 Comments · Uncategorized

I was eager to try the ATMEGA32U4 so I ordered a Teensy2. In this post I will adapt the sd-reader library previously tested with an ATMEGA168 to the Teensy2.

Teensy 2.0 ATMEGA32U4 top

Converting the Teensy2 to 3.3V

The Teensy2 can be powered by a 3.3V regulator. The conversion is described here.

The regulator is soldered underneath the board. Then you have to cut a small trace between two pads and solder two others to use the power from the regulator instead of the 5V coming from the USB.

Teensy 2.0 ATMEGA32U4 bottom with 3.3V regulator soldered

The ATMEGA32U4 itself contains a 3.3V regulator but it is used only to power the D+ and D- USB pads.

Connecting the SD card to the board

Like in my previous post, the SD card is connected to the SPI interface. It is located on pins PB0-3 on the Teensy. I also connect my serial adapter on the RX/TX interface:

Schematic of SD card connected to Teensy 2.0

Teensy2 connected to a SD card - breadboard circuit

Porting sd-reader to the Teensy2

A few changes are required to compile the library.

A new pin configuration for the ATMEGA32U4 SPI interface is added in sd_raw_config.h:

...
#elif defined(__AVR_ATmega32U4__)
    #define configure_pin_mosi() DDRB |= (1 << DDB2)
    #define configure_pin_sck() DDRB |= (1 << DDB1)
    #define configure_pin_ss() DDRB |= (1 << DDB0)
    #define configure_pin_miso() DDRB &= ~(1 << DDB3)
 
    #define select_card() PORTB &= ~(1 << PORTB0)
    #define unselect_card() PORTB |= (1 << PORTB0)
#else
...

The ATMEGA32U4 uses different constants for the UART register in uart.c:

...
#elif defined(UDR1)
#define UBRRH UBRR1H
#define UBRRL UBRR1L
#define UDR UDR1
 
#define UCSRA UCSR1A
#define UDRE UDRE1
#define RXC RXC1
 
#define UCSRB UCSR1B
#define RXEN RXEN1
#define TXEN TXEN1
#define RXCIE RXCIE1
 
#define UCSRC UCSR1C
#define URSEL 
#define UCSZ0 UCSZ10
#define UCSZ1 UCSZ11
#define UCSRC_SELECT 0
#else
...
#elif defined(USART1_RX_vect)
#define USART_RXC_vect USART1_RX_vect
#elif defined(USART_RX_vect)

I also enable the FAT32 capability in fat_config.h:

#define FAT_FAT32_SUPPORT 1

In the Makefile, I change the MCU type and the binary size display format:

MCU := atmega32u4
...
SIZE = avr-size -A --format=avr --mcu=$(MCU)

Here is the result of the build with the FAT32 capability enabled:

AVR Memory Usage
----------------
Device: atmega32u4

Program:   16204 bytes (49.5% Full)
(.text + .data + .bootloader)

Data:        742 bytes (29.0% Full)
(.data + .bss + .noinit)

The compiled application uses 16204 bytes of FLASH and 742 bytes of RAM.

First test: garbled output

I download sd-reader.hex on the Teensy2 using the loader application from PJRC and connect the serial adapter at 9600 bauds:

$ cu -s 9600 -l /dev/tty.usbserial
Connected.
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

Not good. The reason of the problem is that on the stock Teensy2 the CLKDIV8 fuse is enabled by default so the clock frequency is divided by 8 (according to this comment). Then the Teensy2 runs at 2 MHz, but in the Makefile we specified F_CPU at 16MHz. This causes a miscalculation of the baudrate constant in uart.c:

#define UBRRVAL (F_CPU/(BAUD*16)-1)

To correct this we have to change the MCU clock prescaler at the beginning of the main function:

#if (BOARD == TEENSY2)
    /* Set the clock prescaler */
    clock_prescale_set(clock_div_1);
#endif

With this setting the Teensy2 runs at 16 MHz. But the ATMEGA32U4 is not rated to runs at this frequency with a 3.3V power supply (but it seems to work nonetheless). It is more safe to use it at 8Mhz:

#if (BOARD == TEENSY2)
    /* Set the clock prescaler */
    clock_prescale_set(clock_div_2);
#endif

And in the Makefile:

F_CPU := 8000000L

Second test: reading a FAT32 card

The UART now works coorectly and I am able to enter commands in the sd-reader shell. Here is the result with a FAT32 2GB micro SD card:

$ cu -s 9600 -l /dev/tty.usbserial 
Connected.
manuf:  0x03
oem:    SD
prod:   SU02G
rev:    80
serial: 0x201b858a
date:   8/7
size:   1938MB
copy:   1
wr.pr.: 0/0
format: 0
free:   2027241472/2028630016
> ls
NO                                   0
._.Trashes                           4096
.Trashes/                            0
.Spotlight-V100/                     0
> mkdir test
> cd test
> touch data
> write data 0
< input 0
< input 2
< input 4
< 
> ls
./                                   0
../                                  0
data                                 21
> cat data
00000000: 69 6e 70 75 74 20 30 69 input 0i
00000008: 6e 70 75 74 20 32 69 6e nput 2in
00000010: 70 75 74 20 34 32 69 6e put 4
> 

Source code

Patch to apply on sd-reader_source_20090330.zip

Tags: ··

8 Comments so far ↓

  • Bits1

    Hello!

    I have a few questions regarding the SD card and the Teensy. In the new Teensyduino 0.9, you could have the option of making the teensy with the SD card into a serial port. I have done some research that tells me I can have the teensy request the computer to search for a document and listens for the computer to respond whether it finds the document or not. If it did, then the teensy can have the computer transfer the documents in bits over to the teensy, which will create the file with that same name and dump all the data into it. Once its finish, the teensy can blink the light to notify the user. I can see that this is possible, however, I have not seen any EXAMPLES or any projects that has something to do with file transfer from computer to Teensy and serial ports with the Teensy. The SdFat library do contain some examples about creating file but it only generates files within the root directory, which is the SD card. If I were to send commands on the terminal to send files to the serial port (teensy in disguise) , I’m doing this on the user’s behalf and so I worry about permissions. Do root users only have the rights to read and write files? What about the regular users who do NOT have administration rights? I saw your post here that you could read the sd card so I was wondering if you know whether there is any way to have the Teensy communicate with the computer too?

    Thank you for your help,

    Bits1

  • The Chief Sheep

    @Bits1

    Hi, I am sorry I do not really understand your use case. I am not really familiar with the Teensyduino environment.

    With the SDFat library you should be able to write data coming from any user over the serial port to the SD card. There is no right management limitations with FAT. It also looks like you are confusing the root directory of a file system and the root user of an operating system. If a user is able to transfer data to the Teensy through the serial port then there is no restriction to write those data on the SD.

  • Jeffrey

    Hello,

    Do we have to change the source code if we need to use a SD card with other size (other than 2GB) ?

  • The Chief Sheep

    @Jeffrey,
    I don’t think you need any modification.
    The sd-reader library automatically detects the size of the SD card during its initialization and claims to support MMC, SD and SDHC cards. So you should be able to read card up to 32GB in size (But I have only tested it with 2GB cards so I can’t vouch for it).

  • DaberMania

    Very good overview. I put together a tutorial on connecting the SDCard reader to the Teensy++ and how to access it with SDFat. My focus with the use of Teensy is for pentesting and learning how to leverage the HID drivers in Windows for malicious activity. Here is my site with the information and tutorial for Teensy++ [dabermania.blogspot.com/2011/04/teensy-sd-card-access-with-sdfat.html]

  • The Chief Sheep

    @DaberMania,
    Nice article about injecting an executable using a HID keyboard profile that clearly demonstrate the lack of security of HID. Any USB device can identify itself as a keyboard and inject keystrokes into an unsuspecting computer.

  • Bojana

    hello. I have a ask something. How it would look code if I should use ATMEGA16? I have some homework to do, and I don’t know how! I suppose to write and read to sd card in raw format. And the data wich I write on sd card i suppose to display on lcd monitor. This should be done in micro C, for ATMEGA16 microcontoler. If someone have any idea i will be very thankfull. Or if someone have the code, that would be great!

  • The Teensy 2.0 | AndrĂ©'s Blog

    [...] of all, the mentioned UART1 in stead of UART0, and probably some other register changes. There is a patch available against an old version of this code. I suppose I should analyse the changes and apply them to the [...]

Leave a Comment