Wednesday, October 23, 2013

Music and girls cause boy engineers to kill people unknowingly

There was an engineer. He had been partying all weekend with his peeps at NH7 weekender 2013, Pune. He loved every moment of it. Specially when on the last day the performers urged the crowd to shout "Fuck that shit" in unison. It was thrilling. He shook his neck with the crowd with every chant, the last of which caused his head to come real close to the mouth of a girl making her way to the front. "Excuse me" she said. Her words missed in the loudness, but a few fragments of virii from her breathe made way into his mouth as he breathed in for the next chant.

Its Monday, he is at his office in Pune and suffering from viral infection. The agony induced by illness decreased his attention level at work. He was working on the layout of an ASIC for a baseband processor. A sneeze and an involuntary contraction later, a channel was offset by 5 nm from its intended location. The chip turned out OK. All tests were passed. Except that a series of cascade events (80.67 deg celsius temperature + battery at 75.3% causing power supply to baseband chip at exactly 3.145 volts) causes the unintentional parasitics to boost the BER to extreme levels for a few seconds.

Another engineer buys a phone. It has this baseband processor in it. This engineer has OCD. He always charges his phone for 1 hour at 8 am when he reaches office daily on time. So his battery level crosses 75.3% everyday somewhere around afternoon, exact time being dependent on his usage and ambient weather conditions. He lives and works in Delhi, India. He has a girl friend who is contemplating breaking up with him. It's summer. They are whatsappingeach other. He is trying his best to put forward his case to get her to reconsider breaking up with him. He is winning but the whole conversation is taking its toll on him. Anxiety levels are high. His phone on vibration only (silence must be observed in office) constantly clutched in his hand is draining its battery and his body head is causing phone to warm up. The baseband processor is hot from all the data passing through it.

His hand has increased the thermal resistance and the baseband processor is working up its internal temperature.

Battery draining towards 75.3%...

Power to the chip falling very slowly towards 3.145 volts...

The chip itself warming up to 80.67 degrees...

Anxiety levels increasing...

And finally it happens... The intersection of those exact conditions occurs and the RF receiver frontend of the baseband processor destabilizes and it's Bit Error Rate rises exponentially. A few milliseconds later, the chip resets itself and the message from his girlfriend reaches him exactly 3.14159 seconds later than the time it would have reached him if the baseband processor hadn't reset. The phone vibrates at the opportune time while he was compiling the release binary for the code he was working. The vibration steals his attention away from his screen which is scrolling build messages. His girlfriend isn't going to break up with him. He is happy. A minor warning from the compiler goes un-noticed.

A few years later, that software (that the 2nd engineer was working on) which runs inside a pacemaker kills 3 of its 9,576 owners. A stack overflow on the 37th impulse caused the next 3 impulses to be displaced by 200 milliseconds as the software recovered during a cardiac event occurring exactly 49.7 days after the previous event.

Tuesday, October 22, 2013

Using the EEPROM on LM4F232H5QD using StellarisWare driverlib

NOTE: TI renamed Stellaris LM4F232H5QD to Tiva C Series TM4C123GH6PGE - Both these part numbers refer to the same chip. StellarisWare is now superseded by/renamed to TivaWare 2.0. The LM4F232 USB+CAN Evaluation Kit is now rebranded as Tiva™ C Series TM4C123G USB+CAN Development Kit. This blog post refers to the old StellarisWare (SW-LM3S-9107(Stellarisware).exe) and old CodeComposer Studio (CCS5.2.1.00018_win32) and the old part numbers for the microcontroller chip and the evaluation kit.

If you have an LM4F232H5QD Evaluation Board, here is how to use LM4F232H5QD's on chip EEPROM:
  1. Install the development tools - to know how refer steps 1 to 5 of my previous post. Make sure to use the latest version of StellarisWare - the one for LM3S as well as LM4F. On the date of this post, the latest version was SW-LM3S-9453.exe
  2. Make sure that the file "driverlib-cm4f.lib" exists at "C:\StellarisWare\driverlib\ccs-cm4f\Debug". If it doesn't, here is how to build it:
    1. Start Code Composer, click on File>Import>Existing CCS Eclipse Projects.
    2. Browse to C:\StellarisWare\driverlib and import the "ccs-cm4f" project.
    3. Once that is done, right click on the project and click build and driverlib-cm4f.lib will be generated at C:\StellarisWare\driverlib\ccs-cm4f\Debug
  3. Select File>New>CCS Project to create a new project with the following settings:
    1. Project name: eeprom_test
    2. Family: ARM
    3. Variant: Cortex M | Stellaris LM4F232H5QD 
    4. Connection: Stellaris In-Circuit Debug Interface
    5. Template: Empty Project (with main.c)
  4. Replace the content of main.c with the following lines of code:
  5.  1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    #include "stdio.h"
    #include "stdlib.h"
    #include "file.h"
    
    #include "inttypes.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/rom.h"
    #include "utils/uartstdio.h"
    #include "driverlib/eeprom.h"
    
    #define EEPROM_TEST_ADDRESS 0x0000
    
    struct eeprom_test_t {
     uint8_t a;
     uint8_t b;
     uint16_t c;
     uint8_t d[12];
    } eeprom_write = { 5, 7, 11223, "Hello World" }, eeprom_read = { 0, 0, 0, { 0 } };
    
    int main(void) {
    
     unsigned long esize, eblock;
    
     // Enable lazy stacking for interrupt handlers.  This allows floating-point
     // instructions to be used within interrupt handlers, but at the expense of
     // extra stack usage.
     ROM_FPULazyStackingEnable();
    
     // Set the clocking to run directly from the crystal.
     ROM_SysCtlClockSet(
       SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ
         | SYSCTL_OSC_MAIN);
    
     //We will be using the UART0 of LM4F232H5QD as console for printing the output
     //When LM4F232H5QD Evaluation Kit is connected to the PC, it enumerates as a virtual serial port
     //Use a terminal program like https://sites.google.com/site/braypp/terminal to open the port at 115200 8-N-1
     ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
     ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
     ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
     ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
     UARTStdioInit(0);
     UARTprintf("EEPROM Test Program for LM4F232H5QD\n");
    
     ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_EEPROM0);
     EEPROMInit();
    
     esize = EEPROMSizeGet();
     UARTprintf("on-chip EEPROM Size is %d bytes\n", esize);
    
     eblock = EEPROMBlockCountGet();
     UARTprintf("on-chip EEPROM number of blocks: %d\n", eblock);
    
     UARTprintf("Writing structure to EEPROM at address %u: {%u,%u,%u,%s}\n",
       EEPROM_TEST_ADDRESS, eeprom_write.a, eeprom_write.b, eeprom_write.c, eeprom_write.d);
     EEPROMProgram((unsigned long *)&eeprom_write, EEPROM_TEST_ADDRESS, sizeof(eeprom_write));
    
     EEPROMRead((unsigned long *)&eeprom_read, EEPROM_TEST_ADDRESS, sizeof(eeprom_read));
     UARTprintf("Read structure from EEPROM at address %u: {%u,%u,%u,%s}\n",
       EEPROM_TEST_ADDRESS, eeprom_read.a, eeprom_read.b, eeprom_read.c, eeprom_read.d);
    
     while (1) {
     }
    }
    
  6. Now we need to perform some project settings. Right click on the "eeprom_test" project and select "Project Properties" and perform the following configurations:
    1. Build>ARM Compiler>Include Options. Add the following two paths to the "#include search path":
           "C:\StellarisWare"
           "C:\StellarisWare\boards\ek-lm4f232"
    2. Build>ARM Linker>File Search Paths Options. Add the following two paths to the "Include Library File" (in this order):
           "libc.a"
           "C:\StellarisWare\driverlib\ccs-cm4f\Debug\driverlib-cm4f.lib"
    3. Build>ARM Compiler>Advanced Options>Predefined symbols. Add the following 3 lines to Pre-define NAME (in this order):
           ccs="ccs"
           PART_LM4F232H5QD
           TARGET_IS_BLIZZARD_RA1
    4. ARM Compiler>Advanced Options>Language Options: Enable Support for GCC Extensions.
    5. ARM Compiler>Advanced Options>Assembler Options: Use unified assembly language must be checked.
    6. ARM Compiler>Advanced Options>Runtime Model Options: Place each function in separate subsection must be "on".
    7. ARM Linker>Basic Options: C System Stack size must be set to 512 bytes.
  7. Add the UART printf utility module:
    1. Right click the project "eeprom_test" (in Project Explorer view) and select New>Folder and create a folder named "drivers"
    2. Right click on this newly created "drivers" folder and select "Import"
    3. Select "General>File System"
    4. Browse to C:\StellarisWare\utils
    5. Check only the box next to uartstdio.c
    6. Click Advanced and tick "Create links in workspace"
    7. Click Finish
  8. Build the project (Ctrl+B)
  9. Enter debug mode (press F11)
  10. Start a serial terminal software (like Bray's Terminal) and open COM port enumerated as the Stellaris Virtual Serial Port with the settings 115200 8-N-1. You can look up the COM port number using Device Manager as shown below. The output of our EEPROM test program will be displayed on the terminal software.
    Using Device Manager to look up the COM port number
  11. Switch to Code Composer and press F8 to Run the program on LM4F232H5QD. 
  12. Observe the output on Bray's Terminal.
Output of EEPROM test program as observed on the Serial Terminal software
You can refer to Chapter 6 of C:\StellarisWare\docs\SW-DRL-UG-9453.pdf  for reference of all the EEPROM API

Kent Mini water softner installation notes

I recently bought a Kent Mini Water Softener for my home in Wakad, Pune, India.
I ordered it online for INR 6000/- and it was promptly delivered within the week.
Due to perennial shortage of fresh water, the limited amount of water that Pimpri Chinchwad Municipal Corporation supplies to our homes is only routed to our kitchen.
For bathrooms, we are supplied with groundwater fetched from wells and delivered to out homes by water tanker trucks. This water leaves white stains on the tiles and fittings, interferes with proper washing on clothes, and causes hairfall. The last factor being the most agonizing one that prompted me to get atleast one of my bathrooms fitted with a water softener. Taking bath with hard water left my scalp itchy and hair sticky and rough.
For the various problems caused by hard water and how this device from Kent is supposed to solve them, have a look at the two videos below:

Hard water while cooking
Hard water for washing clothes

Like most water softener, Kent's Mini Water Softener also works on the principle of ion exchange. Watch this video to understand the principle behind its working. PLEASE NOTE THAT A WATER SOFTENER DOES NOT KILL MICROBES OR PURIFY THE WATER. IT ONLY REMOVES THE CALCIUM AND MAGNESIUM IONS FROM IT.

After the delivery of the water softener, I waited for 1-2 weeks for Kent to contact me for scheduling an installation visit from their personnel. Finally, I had to call the service center and explicitly ask them to send someone over for the installation. When the service guy visited, unfortunately there was a power cut and he was unable to carry out the installation (he needed electricity for the drill machine for mounting the water softener on the wall). Now I wanted the water softener installed in one of my bathroom, I wanted to be able to use it to softener the water flowing through my geyser and shower (for washing hair). I realised that this would require some extensive work. The service guy had no experience in installing the water softener in the way I wanted. I decided to research and plan this installation myself. So I asked the service guy to not carry out any installation work himself and instead asked him to explain to me the details of the installation process before he left. He was very helpful.
I spent a couple of days, procrastinating, planning and thinking of components I would need for the installation. Here are some notes on how I finally got around to executing this project:
Various components of the water softener,
refer to this diagram while reading the notes below.
Diagram taken from the user manual. PDF here.

The mounting bracket

For the wall mount bracket, Kent had supplied four pairs of wall plugs and zinc plated screws. You need an 8mm diameter masonry drill bit to mount these. I used 10mm by mistake (for the upper two mounting screws) due to which I ended up with holes which were too wide for the plastic wall plugs supplied by them. So I had to use some portland cement (grey cement) to narrow the holes a bit again before stuffing the Kent supplied plastic wall plugs in them to make sure they fit in snugly.

Note that Kent provides you with a sticker to assist with the mounting of the top two holes. Once the top two holes, you can hang the mounting bracket and then use a pen to mark the bottom two holes.

Mounting assist for the top two screws of the mounting bracket

For the lower two mounting holes, I used my own pair of plastic wall plug and stainless steel screws. Stainless steel (SS) screws are better than simple zinc plated ones. Also, I have become accustomed to using these particular size and make of SS screws and the associated wall plugs - they go well together and fit really snugly inside holes made by my 3/16" (5 mm) masonry drill bits.

The screws that I used
Mounting bracket post installation
Bolting the rasin housing cap to the mounting bracket.
The supplied four hex head bolts can be fasten using
a wrench (or automatic screwdriver) with a size
10mm hex socket

Cutting the CPVC Pipe and mating the Water softener pipes to it

The plumbing of my apartment building is composed to CPVC pipes and joints. There is a segment of NPS 3/8 CPVC pipe (internal diameter 0.473 inch) located just after the main control valve of the bathroom I was working in. I turned off the main valve and cut pipe with a hack saw in two places. A section of pipe had now been removed. I now had the two points on the main piping which I would connect to the inlet and the outlet fittings of the water softener.

The cut segment of the CPVC pipe

Confirming the diameter of the CPVC pipe
Average internal diameter 0.473 inch. Refer Wikipedia entry on Nominal Pipe Size,
according to which this CPVC pipe is NPS 3/8 | SCH 80


Still a work in progress...



Wednesday, October 16, 2013

Inside microSD Cards

This is an old post from Bunnie's blog, but makes a fascinating read. Welcome to the world of counterfeit electronic components! http://www.bunniestudios.com/blog/?p=918 

Monday, October 14, 2013

__attribute__((packed)) with Code Composer (Texas instruments TI ARM GCC)

NOTE: TI renamed Stellaris LM4F232H5QD to Tiva C Series TM4C123GH6PGE - Both these part numbers refer to the same chip. StellarisWare is now superseded by/renamed to TivaWare 2.0. The LM4F232 USB+CAN Evaluation Kit is now rebranded as Tiva™ C Series TM4C123G USB+CAN Development Kit. This blog post refers to the old StellarisWare (SW-LM3S-9107(Stellarisware).exe) and old CodeComposer Studio (CCS5.2.1.00018_win32) and the old part numbers for the microcontroller chip and the evaluation kit.

So if you are writing code for some kinds of networking protocol for TI Stellaris Cortex M4 processors like LM4F232H5QD, you might end up using __attribute__((packed)) for various structures. (Details here)

If you haven't enabled the correct options for your arm-gcc supplied as part of Code Composer, you might get the following error for struct defined with :

"..\prot.h", line 23: error #80: expected a type specifier

To fix that you need to enable support for GCC extensions for your CCS project like so:


More details here

Sometimes importing a project from one CCS eclipse workspace to another CCS eclipse workspace, might cause this option to be reset. 

Friday, October 4, 2013

Reading and Writing to serial port in Linux (Ubuntu)

Here is a small program to write a string to the serial port and read a string from it.
I used it to test the UART echo program for LM4F232H5QD.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdio.h>
#include <termios.h> //header contains the definitions used by the terminal I/O interfaces 
#include <unistd.h> //read() write() close()
#include <fcntl.h>
#include <string.h>

//Serial port defines and variables:
#define BAUDRATE B115200
#define SERIAL_PATH "/dev/ttyUSB0"
int serial_fd;
int serial_read_ret, serial_write_ret;
struct termios serial_settings;
char serial_buffer_send[1024] = "Test";
char serial_buffer_recv[1024] = {0};

int main() {
 printf("Program to write a string to the serial port and read a string from it.\n");
 printf("Make sure to run this program with elevated privileges.\n\n");
 printf("Opening %s in Read/Write mode at 115200 8-N-1...",SERIAL_PATH);
 
 fflush(stdout);
 //Try opening serial port
 serial_fd = open(SERIAL_PATH,O_RDWR|O_NOCTTY);
 if(serial_fd == -1) { //Checks the availability of the Serial Port
  printf("Failed.\n");
  fflush(stdout);
  return 0;
 } else {
  printf("Success.\n");
  fflush(stdout);

  //Get serial port settings
  tcgetattr(serial_fd, &serial_settings); //Get Current Settings of the Port
  cfsetispeed(&serial_settings,BAUDRATE); //Set Input Baudrate
  cfsetospeed(&serial_settings,BAUDRATE); //Set Output Baudrate
  serial_settings.c_cflag &= ~PARENB; //Mask Parity Bit as No Parity
  serial_settings.c_cflag &= ~CSTOPB; //Set Stop Bits as 1 or else it will be 2
  serial_settings.c_cflag &= ~CSIZE; //Clear the current no. of data bit setting
  serial_settings.c_cflag |= CS8; //Set no. of data bits as 8 Bits
 }

 serial_write_ret = write(serial_fd,serial_buffer_send,strlen(serial_buffer_send));
 printf("Sent to serial port: %s\n",serial_buffer_send);

 serial_read_ret = read(serial_fd,serial_buffer_recv,sizeof(serial_buffer_recv));
 printf("Read from serial port: %s\n",serial_buffer_recv);

 serial_read_ret = close(serial_fd); //Close the serial port

 printf("Serial port closed.\n\n");
 return 0;
}

Output: