Why is the default value of WHOAMI register of MPU9250 is 0x71? - microcontroller

I'm reading the datasheet of MPU9250 and I find out the address of MPU6050 inside MPU9250 is b110100x. But when I see the description of WHOAMI register, it says the default value is 0x71. And I cannot figure out any relationship between b110100x and 0x71.
Can anyone tell me what is going on? Thank you~
BTW why does everyone put 0 in front of the address and say that the address of MPU9250 is 0x68? It seems more sense to put 0 on the LSB since that LSB represent read or write.

Related

Understanding SD card read sequence in SPI mode

I'm trying to understand how data is read from an SD card in SPI mode, down to the lowest level (because of an upcoming project of mine).
My setup:
Arduino with SD.h library connected to standard SD card breakout with a logic analyser connected to important pins.
What I know so far:
I went through the initialisation process and I totally understand it now, but when it tries to read I get a little lost;
After the card init is done, the program tries to read from the address 0 with command CMD17: and after this follows some data:
What is weird, is that I could not find what this section of data is representing, it does not appear anywhere in the hexdump of the whole SD card. Only on the second read from the Arduino, at address 0x2000 I get the starting data from the hex dump I'm expecting:
And the beginning of the data packet:
My card is 32G, which is probably SDHC. I should point out that I'm just observing what apparently works and I'm trying to figure out why is that.
My question is, what the data from address 0 meant and why the "start" is at address 0x2000, even if my hexdump shows this data at address 0 (sector 0).

I2C communication between pic32 and MPL3115A2 Altitude/Pressure Sensor

I'm trying to do something really simple and I'm having a bit of trouble getting it to work. I'm working with the MPL3115A2 Altitude/Pressure Sensor and a pic32 uC32 board, and I'm trying to communicate between the two using I2C. (uC32 board is similar enough to arduino that it's practically the same in terms of coding).
I'm using the wire library and I'm simply trying to read register 0x0C from the MPL3115A2, which should give me the device ID.
Here's a code snippet (the define is at the top of the code and the rest is in the main loop):
#define barAddress 0x60
Wire.beginTransmission(barAddress);
Wire.send(0x0C);
Wire.endTransmission();
Wire.requestFrom(barAddress, 1);
uint8_t a = Wire.receive();
Serial.println(a, HEX);
So I start the transmission with address 0x60 (From the datasheet: The standard 7-bit I2C slave address is 0x60 or 1100000. 8-bit read is 0xC1, 8-bit write is 0xC0.). Then I send 0x0C because that's the register I want to access. I then end transmission, and request 1 byte from address 0x60, receive that bit into a 8-bit variable, then print it.
The problem I run into is that when I print it, I just get 0. I don't get the device ID, just 0. No matter what register I try to read, I get 0.
I've been banging my head against a wall for the past few days trying to get this to work. I've attached something I've captured with a logic analyzer, as well as a list of registers from the datasheet of the MPL3115A2 that I've been trying to access.
Using a logic analyzer I can see the clock and data lines. The clock seems normal and the data line gives me the following:
START
Write['192'] + ACK
'12' + ACK
STOP
START
Read['193'] + ACK
'0' + NAK
STOP
This all seems correct to me (192 and 193 come from 8-bit write and read being 0xC0 and 0xC1), except for the '0'. I should be getting the device ID, not 0.
Thanks for any help with this!
You should look at Freescale's app note AN4481, which is referred to by the datasheet. Page 5 shows the single-byte read operation which is what you are doing, except that the register address write must not be followed by a STOP but instead uses a REPEATED-START.
I'm not familiar with the Wire library but it look like all you need to do is remove the Wire.endTransmission(); between the send and requestFrom.
Hopefully, this will solve your problem.

linux-device-driver - serial 8250 loopback driver code?

I want to implement a serial loopback driver code in 8250.c found in /drivers/tty/serial/8250.c as found in linux-3.6.1 kernel.
I do not want to use the hardware loopback(i.e by shorting pin 2(tx) and 3(rx) of the standard serial port), instead I want to modify the 8250.c driver such that, the data from user space will travel from the "serial8250_tx_char" function directly to the "serial8250_rx_char" without going to the hardware, i.e I want to receive what is transmitted?
One possible implementation would be to put the transmission circular buffer data into the tty flip buffer, and then push this data up to the tty core so that the user space can receive it?
I want to know how to do it in the code. We can search the "rx and tx" functions mentioned above-that is where I am looking, and how will I test this, means by writing on the device file and then immediately receiving the same.
I also have a sample patch, but not sure, whether it will work.
Any help would be appreciated...
Abhijit
`## -2112,6 +2116,7 ## static int serial8250_startup(struct uart_port *port)
if (is_real_interrupt(up->port.irq))
up->port.mctrl |= TIOCM_OUT2;
+ up->port.mctrl |= TIOCM_LOOP;
serial8250_set_mctrl(&up->port, up->port.mctrl);
/* Serial over Lan (SoL) hack:
This will set UART to work in internal loop-back mode.`

How to check if the PIN has a certain value

I'm developing on a mobile gsm platform and I need to know the PIN in order to change it. Is there a way to verify if the PIN has a certain value?
I'm looking for the solution that makes use of AT commands since this is the only way to control the gsm modem.
I need this to prevent the use of the SIM card for data transfer, calls etc in personal phones or other devices.
Is there a simple way to find out what the PIN is (highly unlikely) or to check if the PIN is the one from a list of expected values?
Thanks
You cannot extract the pin with the standard command set, AT+CPIN=XXXX will respond with OK if XXXX is the correct pin, otherwise it will generate a CME error - however submitting 3 incorrect attempts can cause the SIM to lock until the PUK code is entered.
If you know the PUK however, you could always change the pin to a known value without needing the original PIN (AT+CPIN again).

Arduino Bootloader

Can someone please explain how the Arduino bootloader works? I'm not looking for a high level answer here, I've read the code and I get the gist of it.
There's a bunch of protocol interaction that happens between the Arduino IDE and the bootloader code, ultimately resulting in a number of inline assembly instructions that self-program the flash with the program being transmitted over the serial interface.
What I'm not clear on is on line 270:
void (*app_start)(void) = 0x0000;
...which I recognize as the declaration, and initialization to NULL, of a function pointer. There are subsequent calls to app_start in places where the bootloader is intended to delegate to execution of the user-loaded code.
Surely, somehow app_start needs to get a non-NULL value at some point for this to all come together. I'm not seeing that in the bootloader code... is it magically linked by the program that gets loaded by the bootloader? I presume that main of the bootloader is the entry point into software after a reset of the chip.
Wrapped up in the 70 or so lines of assembly must be the secret decoder ring that tells the main program where app_start really is? Or perhaps it's some implicit knowlege being taken advantage of by the Arduino IDE? All I know is that if someone doesn't change app_start to point somewhere other than 0, the bootloader code would just spin on itself forever... so what's the trick?
Edit
I'm interested in trying to port the bootloader to an Tiny AVR that doesn't have separate memory space for boot loader code. As it becomes apparent to me that the bootloader code relies on certain fuse settings and chip support, I guess what I'm really interested in knowing is what does it take to port the bootloader to a chip that doesn't have those fuses and hardware support (but still has self-programming capability)?
On NULL
Address 0 does not a null pointer make. A "null pointer" is something more abstract: a special value that applicable functions should recognize as being invalid. C says the special value is 0, and while the language says dereferencing it is "undefined behavior", in the simple world of microcontrollers it usually has a very well-defined effect.
ATmega Bootloaders
Normally, on reset, the AVR's program counter (PC) is initialized to 0, thus the microcontroller begins executing code at address 0.
However, if the Boot Reset Fuse ("BOOTRST") is set, the program counter is instead initialized to an address of a block at the upper end of the memory (where that is depends on how the fuses are set, see a datasheet (PDF, 7 MB) for specifics). The code that begins there can do anything—if you really wanted you could put your own program there if you use an ICSP (bootloaders generally can't overwrite themselves).
Often though, it's a special program—a bootloader—that is able to read data from an external source (often via UART, I2C, CAN, etc.) to rewrite program code (stored in internal or external memory, depending on the micro). The bootloader will typically look for a "special event" which can literally be anything, but for development is most conveniently something on the data bus it will pull the new code from. (For production it might be a special logic level on a pin as it can be checked nearly-instantly.) If the bootloader sees the special event, it can enter bootloading-mode, where it will reflash the program memory, otherwise it passes control off to user code.
As an aside, the point of the bootloader fuse and upper memory block is to allow the use of a bootloader with no modifications to the original software (so long as it doesn't extend all the way up into the bootloader's address). Instead of flashing with just the original HEX and desired fuses, one can flash the original HEX, bootloader, and modified fuses, and presto, bootloader added.
Anyways, in the case of the Arduino, which I believe uses the protocol from the STK500, it attempts to communicate over the UART, and if it gets either no response in the allotted time:
uint32_t count = 0;
while(!(UCSRA & _BV(RXC))) { // loops until a byte received
count++;
if (count > MAX_TIME_COUNT) // 4 seconds or whatever
app_start();
}
or if it errors too much by getting an unexpected response:
if (++error_count == MAX_ERROR_COUNT)
app_start();
It passes control back to the main program, located at 0. In the Arduino source seen above, this is done by calling app_start();, defined as void (*app_start)(void) = 0x0000;.
Because it's couched as a C function call, before the PC hops over to 0, it will push the current PC value onto the stack which also contains other variables used in the bootloader (e.g. count and error_count from above). Does this steal RAM from your program? Well, after the PC is set to 0, the operations that are executed blatantly "violate" what a proper C function (that would eventually return) should do. Among other initialization steps, it resets the stack pointer (effectively obliterating the call stack and all local variables), reclaiming RAM. Global/static variables are initialized to 0, the address of which can freely overlap with whatever the bootloader was using because the bootloader and user programs were compiled independently.
The only lasting effects from the bootloader are modifications to hardware (peripheral) registers, which a good bootloader won't leave in a detrimental state (turning on peripherals that might waste power when you try to sleep). It's generally good practice to also fully initialize peripherals you will use, so even if the bootloader did something strange you'll set it how you want.
ATtiny Bootloaders
On ATtinys, as you mentioned, there is no luxury of the bootloader fuses or memory, so your code will always start at address 0. You might be able to put your bootloader into some higher pages of memory and point your RESET vector at it, then whenever you receive a new hex file to flash with, take the command that's at address 0:1, replace it with the bootloader address, then store the replaced address somewhere else to call for normal execution. (If it's an RJMP ("relative jump") the value will obviously need to be recalculated)
Edit
I'm interested in trying to port the bootloader to an Tiny AVR that doesn't have separate memory space for boot loader code. As it becomes apparent to me that the bootloader code relies on certain fuse settings and chip support, I guess what I'm really interested in knowing is what does it take to port the bootloader to a chip that doesn't have those fuses and hardware support (but still has self-programming capability)?
Depending on your ultimate goal it may be easier to just create your own bootloader rather than try to port one. You really only need to learn a few items for that part.
1) uart tx
2) uart rx
3) self-flash programming
Which can be learned separately and then combined into a bootloader. You will want a part that you can use spi or whatever to write the flash, so that if your bootloader doesnt work or whatever the part came with gets messed up you can still continue development.
Whether you port or roll your own you will still need to understand those three basic things with respect to that part.

Resources