Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Nokia phone

technical


Table Of Contents

Table Of Contents



Forewords 

The basics 

Notation 

Timing 

When is timing needed?

Building bricks

Checksums 

8 bit negative checksum

8 bit paramblock checksum

16 bit negative checksum

32 bit negative checksum

How much delay shall be done after outs?

How much delay shall be before ins?

Waiting for SDA

Sending a byte

Sending a byte during update of the flash

Writing a 16bit word

Sending a bytestream

Sending a bytestream during update of the flash

Reading a byte

Reading a 16bit word

Reading a bytestream

Communication in general

Execution of commands

Initialization of test mode

Sending the bootstrap and the flash loader

Parameters of the bootstrap

Parameters of the flashloader

Retrieval of the phone information

Flash loader commands

Terminate flashloader (0x07)

Read phone information (0x03)

Read command status (0x04)

Erase block (0x00)

Erase whole flash (0x08)

Read from flash (0x0C)

Write to flash (0x0B)

Forewords

This document is for supplying the appropriate information regarding communication with a Nokia phone. This is based upon researching and using the original "Dejan" flasher. Note that the document does not describes the "basics", i.e. what is a bootstrp loader, what is the flash id, what are the flash loaders, etc.

The basics

To flash a Nokia phone you need a simply I2C device with 3 wires (don't be surprised that "normal" I2C implementation use the same wires for outputting and inputting, we're not doing that). I2C uses only clock (SCL) and data (SDA) to transmit signals. For more information about I2C check phillips.com. The following wires are used:

Fbus RX - SDA in

Fbus TX - SDA out

MBUS - SCL out

Note that you can't retrieve the status of the clock (i.e. there is no SCL in).

Notation

The following acronyms are used:

base port: it is the port where the outputs are connected to (i.e. 378h for "common" LPT1)

status port: it is the port where the input is connected (i.e. 379h for "common" LPT1)

Timing

Timing is the most critical part of any I2C specific software. I2C times at microsec resolution so you need to have a "selfmade" solution, since "off-the-shelves" solutions in the compilers does not exist. To have a briefing on timing check:
https://www.ibiblio.org/pub/Linux/docs/HOWTO/mini/other-formats/html_single/IO-Port-Programming.html

It has some advices on timing. Anyway if you don't have internet connection here's a sum-up of the content:

if you read from a port or write to a port it normally takes about 1 microsec

a 'xchg bx,bx' shall take exactly the same clock-cycles on any 'Pentiums'

there is 'rdtsc' for the Pentiums to retrieve the clock-cycles

When is timing needed?

Basically after every 'out' to the base port. The only exception from that is when you update the flash content. At that time you must NOT wait at all, must transfer the bytestream as fast as you can to the phone.

Building bricks

To "drive" the I2C you should have commands for them. The following will be used:

SDALOW (to set data low)

SDAHIGH (to set data high)

SCLLOW (to set clock low)

SCLHIGH (to set clock high)

All of the ones above does the very same job; sets or clears the appropriate bits on the base port (0th or the 3rd). After outputting the value to the base port, a delay is made as well. To check which wires are connected to which bits on the ports, take a look at:
https://www.beyondlogic.org/spp/parallel.htm

Note that there might be some misunderstanding about SDA. Sadly (or luckily) the original "Dejan" interface connects the input of the SDA to the 7th bit of the status port. This bit the 'busy' flag of the status port originally, which is INVERTED by the hardware itself. Thus when reading the SDA the high bit is actually a low one and vica-versa. For the very same logic, the meaning of SDAHIGH and SDALOW has been swapped (i.e. the make SDA high, the bit must be cleared).

And we have four defines to have "the the ones without waiting after outputting.

SDALOWNODELAY (to set data low)

SDAHIGHNODELAY (to set data high)

SCLLOWNODELAY (to set clock low)

SCLHIGHNODELAY (to set clock high)

And one is created for the data input:

SDAINNODELAY (to read the SDA)

Checksums

Some data that are sent by the phone is secured with checksums. Let's sum up the type of checksums a NMP uses.

8 bit negative checksum

The algorythm is as follows:

read each and every byte

sum them up

at the end substract the sum from 0 or -1 (it depends where it used)

8 bit paramblock checksum

The algorythm is as follows:

start from -1

read each and every byte

substract them one bye one from the sum

16 bit negative checksum

The algorythm is as follows:

read each and every word

swap them

sum them up

at the end substract the sum from 0

swap the result

32 bit negative checksum

The algorythm is as follows:

read each and every dword

swap them

sum them up

at the end substract the sum from 0

swap the result

How much delay shall be done after outs?

This is quite the cornerstone of the communication (just as generally timing). It turned out by tests that at around 10 microsec must be done after each and every outs (i.e. 10 read from a port or around 1800 clock cycles)

How much delay shall be before ins?

There shell be no delay at all when reading the SDA.

Waiting for SDA

There is two kinds of "delays" implemented with a specific reason. During communication commands and transfers are acknowledged. Algthough there is no specific "time" when the acknowledge comes, thus must wait for them for a specific time. According to I2C specifications the acknowledge must be stable for two times within one clock cycle. That means that you must sample the SDA 2 times and if both sample is the same then you can say that the data line become high or low. The 2 building block is called:

WAITUNTILSDAISLOW (because of hardware inversion, SDA is low when the appropriate bit is HIGH)

WAITUNTILSDAISHIGH (because of hardware inversion, SDA is high when the appropriate bit is LOW)

Sending a byte

The general algorythm (at least according to the I2C specification) is:

must out each and every bit in the byte as follows:

q       Start with the 0th bit

q       Set SDA high or low according to the incoming bit (i.e. if incoming bit is high do SDAHIGH if it's low then SDALOW

q       Pull clock high, i.e SCLHIGH

q       To detect the acknowledge on the bit, SDAINNODELAY must be done (i.e. read the 7th bit from the status port)

q       Pull clock low, i.e. SCLLOW

So the commands described above must be done 8 times (to out each and every bit)

After completion the data line must be cleared, i.e. SDALOW must be done

To read the acknowledge of the whole byte the same method can be used as described in the loop (i.e. SCLHIGH, SDAINNODELAY, SCLLOW) - This acknowledge is not used (not even read) in the current flasher implementations)

Sending a byte during update of the flash

The only difference is the during write to flash no delay must be done, i.e. the appropriate functions must be used (SDALOWNODELAY, ..)

Writing a 16bit word

When writing a word, note that communication is done on a "Motorola" basis (big endian), i.e. first the high byte must be written and then the low byte.

Sending a bytestream

To send more than one byte is not a problem actually you must send the bytes one after each other to the phone. The only difference is that during bytestream transfer (let it be input or output) the interrupts must be disabled (i.e must do a 'cli' before the start of transfer and must do a 'sti' after the last byte). Note that after enabling the interrupts WIATUNTILSDAISHIGH is issued, i.e. to wait for the acknowledge from the phone (that it accepted the byte stream).

Sending a bytestream during update of the flash

There is no difference from the "common" version, only that you must execute the "fast" byte writer function (the one with no delay).

Reading a byte

The general algorythm is as follows:

must out each and every bit in the byte as follows:

q       The first incoming bit will be the 7th

q       Pull clock high (i.e. SCLHIGH)

q       Read the SDA (i.e. SDAINNODELAY)

q       Pull clock low (i.e SCLLOW)

must do it 8 times

must low clock (i.e. SCLLOW)

must ackonwledge the read-in byte. If it was the last one a high bit must be sent to the device (i.e. SDAHIGH, SCLHIGH, SDAINNODELAY, SCLLOW) otherwise a low bit (i.e. SDALOW, SCLHIGH, SDAINNODELAY, SCLLOW). - Note that currently this acknowledging is not used at all in the current flasher implementation

After that both clock and data must be pulled low - Note that currently this acknowledging is not used at all in the current flasher implementation

If you wish to implement the mentioned acknowledging, please note that it is known that the communication does not "tolerate" SDAHIGHs during read.

Note: currently for safety reasons a delay is issued before reading a byte (it is actually ten times the delay used after 'out's (i.e. around 100 microsec).

Reading a 16bit word

When reading a word, note that communication is done on a "Motorola" basis (big endian), i.e. first comes the high byte and then the low byte.

Reading a bytestream

It is quite the same as the one described for write a bytestream. I.e. must read each and every byte one after each other and must disable interrupts before and must enable interrupts after reading.

Communication in general

Generally the access to the flash starts with a bootstrap upload. After execution the bootstrap loader, (mostly) the phone information (like firmware version, flash ID, etc.) can be retrieved. When flash id is detected the appropriate flash loader can be selected and sent to the phone. After the execution of the flash loader, flash commands can be sent to the phone.

Execution of commands

Generally the following is done when a "command" (let it be bootstrap upload, flash loader upload, flash commands execution) is issued to the phone:

must send the bytes connected with the command (i.e. the bootstrap loader, the flash loader or the command blocks)

must wait until SDA gets high (i.e. WAITUNTILSDAISHIGH; check Chapter 8 for explanation)

must send a zerobyte to the phone (to "execute" the command)

must wait until SDA gets low (i.e. WAITUNTILSDAISLOW , so that the command is executed)

After detecting that SDA got low we can say that the specific command has been executed.

Initialization of test mode

The start of the communication is done by requesting test mode for the phone. When a Nokia is powered off but the power-on button is pressed for a very short time, test mode is issued. It means that the phone gets in a special mode, where it accepts communication modules. This is done as follows:

must pull SDA low (i.e. SDALOWNODELAY)

must wait until it surely gets low (i.e. WAITUNTILSDAISLOW)

must pull SDA high (i.e. SDAHIGHNODELAY)

must wait until it surely gets low (i.e. WAITUNTILSDAISHIGH)

If any of the two WAIT.. fails (times out) it means that:

the power-on button has not been pressed

the power on button is not working

the I2C interface is not working

After entering test mode, it must be prepared, so that it will accept commands. This is done according to this:

must pull SDA low (i.e. SDALOW)

must pull SCL low (i.e. SCLLOW)

must pull SCL high (i.e. SCLHIGH)

must pull SCL low (i.e. SCLLOW)

The last three comands are actually a clock-pulse.

After that the phone is ready for communication

Sending the bootstrap and the flash loader

Execution of the two blocks are quite the same. It is done as follows:

must send a word containing the number of bytes that are to be sent to the phone (i.e. the size of the loaders)

must wait until SDA gets low (i.e. WAITUNTILSDAISLOW)

must send the byte stream (please read Chapter 8 for information)

must execute the bootstrap (or the flash-) loader (check Chapter 12.1 for information how to do this)

Parameters of the bootstrap

The bootloader has one parameter. It is the type of the communication (what hardware will the bootstrap communicate with). It is located on the 9th byte (starting from zero). Note that you must recalculate the checksum of the bootstrap (which is the last 16 bit) if you change it. The checksum calculation is a 16 bit negative checksum).

Parameters of the flashloader

The flashloader has three parameters. The first two is the hardware type (like 65 05) the other is the flash id. The parameterblock of the flashloader is not fixed, the flashloader points to it. You must read the word starting on the 14th (zero based) byte (don't forget to swap it after read). The parameterblock is at the offset given by this word. The first parameter ("65") is at the 1st byte of the paramblock (zero based), the second parameter ("05") is at the 4th and the flash id is located starting from the 8th byte (don't forget to make it Big Endian (swap the id) if needed). Note that you must recalculate the checksum of the flashloader (which is the last 16 bit) if you change it. The checksum calculation is a 16 bit negative checksum).

Retrieval of the phone information

After the bootstrap is working the information from the phone can be retrieved. It is done as follows:

must execute the null command (this is mostly the one and only command the bootstrap accepts- for more information check Chapter 12.1)

Read 36 bytes

Read bytes until you get a zero (or maximum 101 bytes) - this will be the firmware version

Read 9 bytes - this will hold the flashid

Thus the size of the phoneram will be 36+9+the number of bytes your read when reading the firmware version

Wait until phone finishes settles (wait until SDA gets free (WAITUNTILSDAISLOW))

The 1st byte is always a 0x90

The last byte is always the checksum of the read in phone info (a 8 bit negative checksum, this time the result must be substracted from -1)

The flash id (32bit) starts from the last minus 8 bytes

Flash loader commands

This section deals with the (identified) commands of the flash loader. Here is the flow how to send commands to the flashloader:

send the identifer of the command

send the parameterblock of the command (-1 if there are no parameters) - note that this is a bytestream write (i.e. you must wait after the last byte until the phone settles (WAITUNTILSDAISLOW) - Note that the last byte of parameterblock is always the checksum on the parameterblock (8 bit paramblock checksum)

Must execute the command (check Chapter 12.1 for information how to do this)

If you have incoming info for the command you must read it otherwise you're finished, you can send the next command

Terminate flashloader (0x07)

This command has no parameterblock at all, and the goal is to finish the session.

Read phone information (0x03)

This command has no parameterblock at all, and the goal is to read the phone information (which has the very same layout as the one we get after executing the boot loader)

Read command status (0x04)

This command has no parameterblock at all, and the goal is to read the status of the last write command (it can be erase as well). The returned structure is as follows:

the status byte (must 0x91 if the command is successfully executed)

a information byte, if it's other than zero a 6 byte long byteblock follows

a terminator byte

Erase block (0x00)

This command has the following layout of parameterblock:

a 24 bit start address (Big Endian, i.e to write 0x200000 you must store exactly, 20 00 00)

a 24 bit end address (same as above)

This command will erase the flash by the given addresses.

Erase whole flash (0x08)

This command has no parameterblock at all, and the goal is to erase the whole flash.

Read from flash (0x0C)

This command has the following layout of parameterblock:

a 24 bit start address (Big Endian, i.e to write 0x200000 you must store exactly, 20 00 00)

a 0

a 24 bit count (how much shall we read - Big Endian)

After executing the command the given number of bytes shall be read from the phone. After the and of the bytestream a 16 bit word must be read as well. If it's other than 0x00FF (after swapping it) it means that there was an error during the execution of the command.

Write to flash (0x0B)

This command has the following layout of parameterblock:

a 24 bit start address (Big Endian, i.e to write 0x200000 you must store exactly, 20 00 00)

an 8 bit negative checksum on the given data (this time substracted from 0) - the "given data" means the data I wish to write to the flash

a 24 bit count (how much shall we read - Big Endian)

After executing the command the given number of bytes shall be written to the phone. After the and of the bytestream a 16 bit word must be read as well. If it's other than 0x00FF (after swapping it) it means that there was an error during the execution of the command. Please don't forget that the flash update actually sends WORDs to the phone and inverts the ACKs of the bits each an every time (i.e. get a ZERO ack on the high byte, and then a ONE ack on the low byte).


Document Info


Accesari: 1590
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2024 )