Rockbox From A Technical Angle ============================== Background [Most, if not all, of this document is completely outdated. You should rather hunt down this info in the Rockbox wiki or source code!] Björn Stenberg started this venture back in the late year 2001. The first Rockbox code was committed to CVS end of March 2002. Rockbox 1.0 was released in June. Booting and (De)Scrambling The built-in firmware in the Archos Jukebox reads a file from disk into memory, descrambles it, verifies the checksum and then runs it as code. When we build Rockbox images, we scramble the result file to use the same kind of scrambling that the original Archos firmware uses so that it can be loaded by the built-in firmware. 1) The built-in firmware starts 2) It looks in the root directory for a file called "archos.mod" (player) or "ajbrec.ajz" (recorder) 3) If it finds one, it loads the file, descrambles it and runs it CPU The CPU in use is a SH7034 from Hitachi, running at 11.0592MHz (recorder) or 12MHz (player). Most single instructions are executed in 1 cycle. There is a 4KB internal RAM and a 2MB external RAM. Memory Usage All Archos Jukebox models have only 2MB RAM. The RAM is used for everything, including code, graphics and config. To be able to play as long as possible without having to load more data, the size of the mpeg playing buffer must remain as big as possible. Also, since we need to be able to do almost everything in Rockbox simultaneously, we use no dynamic memory allocation system at all. All sub-parts that needs memory must allocate their needs staticly. This puts a great responsibility on all coders. Playing MPEG The MPEG decoding is performed by an external circuit, MAS3507D (for the Player/Studio models) or MAS3587F (for the Recorder models). The CPU has a serial connection to the MAS for MP3 playback, using serial port 0 at approx. 1mbit/s. The MAS has a handshake signal called DEMAND, that informs the CPU when it wants more MP3 data. Whenever the DEMAND signal goes high, it wants data sent over the serial line, and it wants it quickly, within ~1ms. When the MAS has received enough data, it negates the DEMAND signal and expects the incoming data stream to stop within 1ms. The DEMAND signal is connected to a port pin on the CPU which can generate an IRQ, but only on the falling edge. That means that the mpeg driver code   must poll the DEMAND signal every ms to keep the MAS happy. The mpeg code does use the IRQ to detect the falling edge when the MAS is "full". Unfortunately, the serial port on the CPU sends the LSB first, and the MAS expects the MSB first. Therefore we have to revers the bit order in every byte in the loaded MP3 data. This is referred to as "bit swapping" in the Rockbox code. The internal DMA controller is used to feed the serial port with data. The driver works roughly like this: 1) Load MP3 data into the RAM buffer 2) Bitswap the data 3) Load the DMA source pointer to the next 64Kbyte block to be transferred 4) Wait until DEMAND is high 5) Enable the DMA 6) Wait until the falling DEMAND pin generates an IRQ 7) Disable the DMA 8) Go to 4 The DMA generates an IRQ when the 64Kbyte block is transferred, and the IRQ handler updates the DMA source pointer. _____________________________ | | DEMAND __________| |_____________ _ _ _ _ _ _ _ _ _ SC0 _____________/ \/ \/ \/ \/ \/ \/ \/ \/ \____________ \_/\_/\_/\_/\_/\_/\_/\_/\_/ ^ ^ | | Poll sees the DEMAND The DEMAND pin generates signal go high and an IRQ that in turn disables enables the DMA the DMA again Spinning The Disk Up/Down To save battery, the spinning of the harddrive must be kept at a minimum. Rockbox features a timeout, so that if no action has been performed within N seconds, the disk will spin-down automaticly. However, if the disk was used for mpeg-loading for music playback, the spin-down will be almost immediate as then there's no point in timing out. The N second timer is thus only used when the disk-activity is trigged by a user. FAT and Mounting Rockbox scans the partitions of the disk and tries to mount them as fat32 filesystems at boot. Directory Buffer When using the "dir browser" in Rockbox to display a single directory, it loads all entries in the directory into memory first, then sorts them and presents them on screen. The buffer used for all file entries is limited to maximum 16K or 400 entries. If the file names are longish, the 16K will run out before 400 entries have been used. This rather limited buffer size is of course again related to the necessity to keep the footprint small to keep the mpeg buffer as large as possible. Playlist Concepts One of the most obvious limitations in the firmware Rockbox tries to outperform, was the way playlists were dealt with. When loading a playlist (which is a plain text file with file names separated by newlines), Rockbox will scan through the file and store indexes to all file names in an array. The array itself has a 10000-entry limit (for memory size reasons). To play a specific song from the playlist, Rockbox checks the index and then seeks to that position in the original file on disk and gets the file name from there. This way, very little memory is wasted and yet very large playlists are supported. Playing a Directory Playing a full directory is using the same technique as with playlists. The difference is that the playlist is not a file on disk, but is the directory buffer. Shuffle Since the playlist is a an array of indexes to where to read the file name, shuffle modifies the order of these indexes in the array. The algorithm is pretty much like shuffling a deck of cards, and it uses a pseudo random generator called the Mersenne Twister. The randomness is identical for the same random seed. This is the secret to good resume. Even when you've shut down your unit and re-starts it, using the same random seed as the previous time will give exactly the same random order. Saving Config Data The Player/Studio models have no battery-backuped memory while the Recorder models have 44 bytes battery-backuped. To save data to be persistent and around even after reboots, Rockbox uses harddisk sector 63, which is outside the FAT32 filesystem. (Recorder models also get some data stored in the battery-backuped area). The config is only saved when the disk is spinning. This is important to realize, as if you change a config setting and then immediately shuts your unit down, the new config is not saved. DEVELOPERS: The config checksum includes a header with a version number. This version number must be increased when the config structure becomes incompatible. This makes the checksum check fail, and the settings are reset to default values. Resume Explained ... Charging (Charging concerns Recorder models only, the other models have hardware- controlled charging that Rockbox can't affect.) ... Profiling Rockbox contains a profiling system which can be used to monitor call count and time in function for a specific set of functions on a single thread. To use this functionality: 1) Configure a developer build with profiling support. 2) Make sure that the functions of interest will be compiled with the PROFILE_OPTS added to their CFLAGS 3) On the same thread as these functions will be run, surround the relevent running time with calls to profile_thread and profstop. (For codecs, this can be done in the codec.c file for example) 4) Compile and run the code on the target, after the section to be profiled exits (when profstop is called) a profile.out file will be written to the player's root. 5) Use the tools/profile_reader/profile_reader.pl script to convert the profile.out into a human readable format. This script requires the relevent map files and object (or library) files created in the build. (ex: ./profile_reader.pl profile.out m68k-elf-objdump vorbis.map libtremor.a 0) There is also a profile_comparator.pl script which can compare two profile runs as output by the above script to show percent change from optimization profile_reader.pl requires a recent binutils that can automatically handle target object files, or objdump in path to be the target-objdump.