Visual Studio Update 1

Illustration

Service pack is forbidden word these days in Redmond. Therefore we got Visual Studio 2012 Update 1. Initial download is only 1 MB with rest of data collected upon setup. Real fun if you need to update multiple computers.

As far as update goes there just aren’t any major improvements. Mostly it is just bug fixes and stuff that ought to be in initial release.

One thing that I do like is how fast this update came after initial release. If they keep up this speed we might get next service pack update in a few months. With obvious stuff gone that means that some goodies will be there. We can only hope.

How to Store Settings Without EEPROM

Having customizable setting in your PIC program is easy. Just define it as a constant and let XC8 handle everything else. If you need to change it during runtime there is bunch of code out there dealing with EEPROM access. But what if you want to store something in PIC without EEPROM?

In my case I needed to store two settings: Counter and Unit. Hardware device was already built around PIC without EEPROM so there was no choice but to use self-programming feature that almost all newer PICs share.

Idea is simple. Reserve some space in program memory by making some data constant (e.g. const char mySetting = 3;). Every time you access this variable PIC will return what it had stored there at time of programming. Our trick is to change those values by reprogramming code as it runs.

First complication comes from fact that you cannot just write in flash willy-nilly. Before each write you need to erase whole block of (usually) 64 bytes. Unless you are willing to write very complicated code that also means that you will always need to occupy whole block regardless of how many bytes you want to actually store.

Second caveat is that you can only erase whole block. That means that you cannot let compiler decide upon location of your data. You must select fixed location and that might give you :0: warning: segment "__SETTINGS_PROGRAM_text" (200-23F) overlaps segment "intcode" (8-273). Fortunately solution is really easy - just move your constant somewhere else. Of course that implies that you have enough free flash memory laying around.

Third issue might be that this operation typically takes few milliseconds which is ages in microcontroller terms. To make things worse interrupts must be disabled during almost all that time. Any precise time keeping is out of question.

However, if you wiggle your way around all these obstacles, you get nice storage for times when you just cannot afford EEPROM for one reason or another.

Full source follows:

#define _SETTINGS_FLASH_RAW { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } //reserving space because erase block is block 32-word (64-bytes)
#define _SETTINGS_FLASH_LOCATION 0x0400

#define _SETTINGS_STORE_EMPTY { 0, 0 }
#define _SETTINGS_STORE_BYTES 2

#define _SETTINGS_REENABLE_GIE_AFTER_WRITE     1

const unsigned char _SETTINGS_PROGRAM[] @ _SETTINGS_FLASH_LOCATION = _SETTINGS_FLASH_RAW;

void _settings_write(int index, unsigned char data) {
    unsigned char newProgram[] = _SETTINGS_STORE_EMPTY;
    for (int i=0; i<_SETTINGS_STORE_BYTES; i++) {
        newProgram[i] = _SETTINGS_PROGRAM[i];
    }
    newProgram[index] = data;

    GIE = 0;

    EEPGD = 1; //point to Flash program memory
    CFGS = 0; //access Flash program memory
    WREN = 1; //enable write to memory

    TBLPTR = _SETTINGS_FLASH_LOCATION;
    FREE = 1; //enable block Erase operation
    #asm //erase block
        MOVLW 55h
        MOVWF EECON2 ; write 55h
        MOVLW 0AAh
        MOVWF EECON2 ; write 0AAh
    #endasm
    WR = 1; //start erase (CPU stall)

    TBLPTR = _SETTINGS_FLASH_LOCATION;
    for (int i=0; i<_SETTINGS_STORE_BYTES; i++) {
        TABLAT = newProgram[i];
        asm("TBLWT*+");
        #asm
            MOVLW 55h
            MOVWF EECON2 ; write 55h
            MOVLW 0AAh
            MOVWF EECON2 ; write 0AAh
        #endasm
        WR = 1; //start program (CPU stall)
    }
    WREN = 0; //disable write to memory

    if (_SETTINGS_REENABLE_GIE_AFTER_WRITE) { GIE = 1; }
}


#define _SETTINGS_INDEX_COUNTER  0

char  settings_getCounter() {
    return _SETTINGS_PROGRAM[_SETTINGS_INDEX_COUNTER];
}

void settings_setCounter(char data) {
    _settings_write(_SETTINGS_INDEX_COUNTER, data);
}


#define _SETTINGS_INDEX_UNIT 1

char  settings_getUnit() {
    return _SETTINGS_PROGRAM[_SETTINGS_INDEX_UNIT] % 3;
}

void settings_setUnit(char data) {
    _settings_write(_SETTINGS_INDEX_UNIT, data);
}

It would be best if you would keep this code in separate file (e.g. settings.h) and just include it from your main program file instead of pasting all this directly.

PS: If your program does not use interrupts change _SETTINGS_REENABLE_GIE_AFTER_WRITE to 0.

PPS: Do notice that flash memory was not intended as this kind of storage medium. Writing is much slower than EEPROM (because of erase) and endurance is much lower. Use it only in dire straits and be gentle.

PPS: This code is for PIC18F* series of micro-controllers. Same general principle works on PIC16F* but names of some registers might differ and additional NOPs might be required. Do check instruction manual.

No More Freebies

Starting December 6th 2012 there is no more free Google Apps. If someone wants Google to handle mail for his domain, he can now expect hefty yearly charge of $50 per user.

All current users of free Google Apps should probably start searching for new home since I don’t expect this status quo to last. My assumption is that existing users will start getting “pay up or get lost” mails pretty soon. For family of four this means $200 if you want to continue using it or dealing with account migration. Lets hope that Google’s “Don’t be evil” motto will prevent this extortion-style scenario from happening.

This unfortunate turn of events just comes to show how living in cloud leaves you in mercy of your hosting company. There is no such things as a free lunch.

Taste of ITU Governance

If you are wondering what ITU can offer if it takes over control of Internet, wonder no more. Great example of moronic and damaging decisions is already here - Y.2770 Requirements for deep packet inspection in Next Generation Networks.

This standardizes the way how government can spy any traffic that goes over your favorite telco. If possible this standard also keeps door open to decrypt user’s traffic “in case of a local availability of the used encryption key(s).”

Whoever thinks that this is good idea and trusts his government is complete moron.

My own government was caught some time ago (translation) just adding unrelated phone numbers to existing warrants. End result is that this practice was deemed quite appropriate. USA government is no better with its whole NSA activities. Lets not even go into areas here warrant are not required. And there is plenty of other governments with even lower standards.

This standardization will allow them to use one kind of equipment in each telco thus reducing their cost of tracking a citizen. Forcing a company to give them SSL keys in order to stop users from encrypting traffic is next step. Hell, I can bet that some countries are already doing that.

Quite a lot of Internet security relies on encrypted things staying encrypted. Once that encryption is taken away all you think of private is not so private anymore. Each time you access your bank in order to make a transaction, someone else is peeking over your shoulders.

And “honest people have nothing to hide” is bullshit. How much time do you think it will pass until some security hole is discovered on those systems?

Same standardization that makes live easy for government will also make it a sweet delight for criminals. Just filter through minute of traffic and you will have enough information to get into thousands of accounts. I will not even cover what single rogue agent can do e.g. if he finds that his wife is cheating him. He can gather/falsify enough information to get other guy in real trouble. And I am being optimistic, real-life scenarios will be much darker.

And this is a mess that ITU is already capable of. Imagine ideas that will spring into their mind if they gain control over Internet. Orwell was right, he just missed the year.

XC8 and Fixup Overflow Referencing Psect BssBANK1

Illustration

For one PIC microcontroller program I had to use assembly code for some critical timing. Rest of code was just plain XC8 C code and everything compiled (and performed) without any issue. So I decided to share code with another project of mine.

Suddenly I got bunch of warnings all saying almost same thing: wait.h:19: error: fixup overflow referencing psect bssBANK1 (0xA2) into 1 byte at 0xB3E/0x2 -> 0x59F (dist/default/production\Source.production.obj 136/0x3E). Program did work (fixup did what its name says) but each compilation would pepper output with warnings - unacceptable.

It was easy to find a culprit:

unsigned char wait_asm_W; //copy of W
...
#asm
    BANKSEL _wait_asm_W
    MOVWF   _wait_asm_W
    ...
#end asm

Address of an variable was used inside assembly code. Original program had this variable in bank0 and thus no warning were issues. This project had slightly different allocations and variable ended up in bank1 (e.g. 0xA2). Since assembly instruction can only deal with 7-bit registers, address was outside of allowed range.

Once solution is forcing variable into bank0:

bank0 unsigned char wait_asm_W; //copy of W
...
#asm
    BANKSEL _wait_asm_W
    MOVWF   _wait_asm_W
    ...
#end asm

This works but only after change to project’s compiler flags (Properties, XC8 global options, XC8 compiler, Option categories: Optimizations, Address qualifiers: Require). Just thought of having to remember to change project properties each time I reuse this code made me wince. Yes, it was a solution but not what I wanted.

What I wanted is way to transform offending value 0xA2 to non-problematic 0x22. Quick bit-masking solved that issue and warnings were gone:

unsigned char wait_asm_W; //copy of W
...
#asm
    BANKSEL _wait_asm_W
    MOVWF   _wait_asm_W & 0x7F
    ...
#end asm