Arduino freezes on lcd.begin()

I am developing standalone special-purpose thermostat unit with ATMega328p-pu, programmed by pulling the chip out from socket into arduino, so I can't really use serial debugging etc...

Can you please provide a schematic and photograph of your board and setup with the i2c adaptor and lcd?

I believe that the sketch freezing at lcd.begin() with no rblink or gblink after the call is likely to indicate a problem on the i2c bus.

How did you determine the address of the i2c backpack?

had to sniff the address (by modifying the SPI_CHECK, i was able to identify the DEC adress by reading number of LED blinks...), it was 0x3F instead of standard 0x20/0x27

SPI_CHECK makes no sense for an i2c device.

You should be using this program modified to show blinks, and with the chip programmed to run it within the actual circuit.

// I2C Scanner
// Written by Nick Gammon
// Date: 20th April 2011

#include <Wire.h>

void setup() {
  Serial.begin (115200);

  // Leonardo: wait for serial port to connect
  while (!Serial) 
    {
    }

  Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;
  
  Wire.begin();
  for (byte i = 8; i < 120; i++)
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
      {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);  // maybe unneeded?
      } // end of good response
  } // end of for loop
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
}  // end of setup

void loop() {}