How to do late board initialization on NuttX

I was looking for a way to call my custom board initialization on NuttX, but when it tries to register a device it was failing because “/dev” (filesystem) wasn’t initialized yet.

I “fixed” it calling my board initialization from arch up_initialize(), then I asked in the NuttX mailing list for a solution similar to U-Boot’s board_late_init. Then Mr. Greg pointed me to BOARD_INITIALIZE feature already present on NuttX:

        bool "Custom board/driver initialization"
        default n
                By default, there are three points in time where you can insert
                custom initialization logic:

                1) _boardinitialize():  This function is used only for
                initialization of very low-level things like configuration of
                GPIO pins, power setting.  The OS has not been initialized
                at this point, so you cannot allocate memory or initialize
                device drivers at this phase.

                2) The next level of initialization is performed by a call to
                up_initialize() (in arch//src/common/up_initialize.c).
                The OS has been initialized at this point and it is okay to
                initialize drivers in this phase.

                3) And, finally, when the user application code starts.

                If BOARD_INITIALIZE is selected, then an additional initialization
                call will be performed in the boot-up sequence to a function
                called board_initialize().  board_initialize() will be
                call between phases 2) and 3) above, immediately after
                up_initialize() is called.  This additional initialization
                phase may be used, for example, to initialize board-specific
                device drivers.

All I need to do is to place my custom initialization inside board_initialize() at stm32_boot.c :

void board_initialize(void)
  /* Perform board initialization */


Algoritmo para calcular a curtose e obliquidade

Hoje precisei calcular a curtose e obliquidade dos dados presentes num histograma. Após alguma pesquisa descobri este site com uma implementação em C++. Alterei a implementação para ficar num único arquivo em C:

#include <stdio.h>
#include <math.h<

long long n;
double M1, M2, M3, M4;

void clear()
    n = 0;
    M1 = M2 = M3 = M4 = 0.0;

void push(double x)
    double delta, delta_n, delta_n2, term1;

    long long n1 = n;
    delta = x - M1;
    delta_n = delta / n;
    delta_n2 = delta_n * delta_n;
    term1 = delta * delta_n * n1;
    M1 += delta_n;
    M4 += term1 * delta_n2 * (n*n - 3*n + 3) + 6 * delta_n2 * M2 - 4 * delta_n * M3;
    M3 += term1 * delta_n * (n - 2) - 3 * delta_n * M2;
    M2 += term1;

long long num_data_values()
    return n;

double mean()
    return M1;

double variance()
    return M2/(n-1.0);

double standard_deviation()
    return sqrt( variance() );

double skewness()
    return sqrt((double)n) * M3/ pow(M2, 1.5);

double kurtosis()
    return (double) ((n)*M4 / (M2*M2) - 3.0);

int main(int argc, const char **argv)
	FILE *f;
	int value;
	char val[32];
	double kurt, skew;
	if (argc < 2) {
		printf("Use: oblicurto filename.txt\n");
		return -1;
	if ((f = fopen(argv[1], "r")) == NULL){
		printf("Cannot open file %s!\n", argv[1]);
		return -1;


	while(fgets(val, 30, f) != NULL){
		value = atoi(val);
		push((double) value);

	skew = skewness();
	kurt = kurtosis();

	printf("Amount = %d | Kurtosis = %f | Skewness = %f   ===>   ", (int) num_data_values(), kurt, skew);


	return 0;

Substituindo o percloreto de ferro por uma solução reaproveitável

Normalmente as pessoas utilizam Percloreto de Ferro para corroer as placas de circuito impresso caseiras, mas ele tem uma desvantagem: a solução “enfraquece” (satura) com o tempo de uso e precisa ser descartada.

Felizmente existe uma alternativa, veja neste Instructables:!–A-better-etc/?ALLSTEPS

O autor da dica acima retirou esta informação deste site:

Nota: Embora o Firefox reporte que o site deste link contém código malicioso, não parece ser o caso (falso positivo?).

I got new Hi3518 IP Camera modules

I got two new IP Camera modules and found its serial pins:

IP Camera Hi3518

U-Boot 2010.06 (Aug 06 2013 - 11:53:06)                                      
DRAM:  256 MiB                                                               
NAND:  Special Nand id table Version 1.35                   
Nand ID: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00            
No NAND device found!!!                                     
0 MiB                                                       
Check spi flash controller v350... Found                    
Spi(cs1) ID: 0xEF 0x40 0x18 0x00 0x00 0x00                  
Spi(cs1): Block:64KB Chip:16MB Name:"W25Q128B"
In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0 
16384 KiB hi_sfc at 0:0 is now current device

## Booting kernel from Legacy Image at 82000000 ...
   Image Name:   Linux-3.0.8
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2724796 Bytes = 2.6 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Loading Kernel Image ... OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Linux version 3.0.8 (root@johhnny-desktop) (gcc version 4.4.1 (Hisilicon_v100(gcc4.4-290+uclibc_0.9.32.1+ea3
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: hi3518
Memory policy: ECC disabled, Data cache writeback
AXI bus clock 200000000.
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 18796
Kernel command line: mem=74M console=ttyAMA0,115200 root=/dev/mtdblock3 rootfstype=cramfs mtdparts=hi_sfc:1)
PID hash table entries: 512 (order: -1, 2048 bytes)
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 74MB = 74MB total
Memory: 69892k/69892k available, 5884k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    DMA     : 0xffc00000 - 0xffe00000   (   2 MB)
    vmalloc : 0xc5000000 - 0xfe000000   ( 912 MB)
    lowmem  : 0xc0000000 - 0xc4a00000   (  74 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .init : 0xc0008000 - 0xc0028000   ( 128 kB)
      .text : 0xc0028000 - 0xc04c9000   (4740 kB)
      .data : 0xc04ca000 - 0xc04e97c0   ( 126 kB)
       .bss : 0xc04e97e4 - 0xc0504e80   ( 110 kB)
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS:32 nr_irqs:32 32
sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 42949ms
Console: colour dummy device 80x30
Calibrating delay loop... 218.72 BogoMIPS (lpj=1093632)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NET: Registered protocol family 16
Serial: AMBA PL011 UART driver
uart:0: ttyAMA0 at MMIO 0x20080000 (irq = 5) is a PL011 rev2
console [ttyAMA0] enabled
uart:1: ttyAMA1 at MMIO 0x20090000 (irq = 5) is a PL011 rev2
bio: create slab  at 0
SCSI subsystem initialized
cfg80211: Calling CRDA to update world regulatory domain
Switching to clocksource timer1
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
NetWinder Floating Point Emulator V0.97 (double precision)
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
JFFS2 version 2.2. (NAND) �© 2001-2006 Red Hat, Inc.
fuse init (API version 7.16)
msgmni has been set to 136
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
io scheduler noop registered
io scheduler deadline registered (default)
io scheduler cfq registered
TS82 driver for HI3518C
Pass authentication ... ... 
brd: module loaded
loop: module loaded
Spi id table Version 1.22
Spi(cs1) ID: 0xEF 0x40 0x18 0x00 0x00 0x00
SPI FLASH start_up_mode is 3 Bytes
spi size: 0x16777216
chip num: 1
4 cmdlinepart partitions found on MTD device hi_sfc
Creating 4 MTD partitions on "hi_sfc":
0x000000000000-0x000000100000 : "boot"
0x000000100000-0x000000400000 : "kernel"
0x000000400000-0x000000480000 : "dataBlock"
0x000000480000-0x000001000000 : "rootfs"
Fixed MDIO Bus: probed
himii: probed
PPP generic driver version 2.4.2
PPP Deflate Compression module registered
PPP BSD Compression module registered
PPP MPPE Compression module registered
NET: Registered protocol family 24
mousedev: PS/2 mouse device common for all mice
TCP cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 10
NET: Registered protocol family 17
NET: Registered protocol family 15
lib80211: common routines for IEEE802.11 drivers
Registering the dns_resolver key type
registered taskstats version 1
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
�VFS: Mounted root (cramfs filesystem) readonly on device 31:3.
Freeing init memory: 128K

            _ _ _ _ _ _ _ _ _ _ _ _
            \  _  _   _  _ _ ___
            / /__/ \ |_/
           / __   /  -  _ ___
          / /  / /  / /
  _ _ _ _/ /  /  \_/  \_ ______

[RCS]: /etc/init.d/S00devs
[RCS]: /etc/init.d/S01udev
udevd (463): /proc/463/oom_adj is deprecated, please use /proc/463/oom_score_adj instead.
CMEMK module: built on Mar  6 2013 at 16:34:50
  Reference Linux version 3.0.8
  File /AppData/his/sdk/Hi3518_SDK_V1.0.3.0/drv_test/cmem/src/module/cmemk.c
allocated heap buffer 0xc6000000 of size 0xe00000
cmemk initialized
*** Board tools : ver0.0.1_20120501  *** 
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0008: 0x00000000 --> 0x00000001 
*** Board tools : ver0.0.1_20120501  *** 
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0018: 0x00000000 --> 0x00000001 
*** Board tools : ver0.0.1_20120501  *** 
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f001c: 0x00000000 --> 0x00000001 
*** Board tools : ver0.0.1_20120501  *** 
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x200f0124: 0x00000000 --> 0x00000000 
*** Board tools : ver0.0.1_20120501  *** 
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x20140400: 0x00000038 --> 0x00000002 
*** Board tools : ver0.0.1_20120501  *** 
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x201403fc: 0x00000034 --> 0x00000002 
ADC_CH0 driver ADC detect
Set IR-CUT default
1111, set ircut to night mod
2222, set ircut to day mod
3333, ircut init
Current ADC. Vol. 92
Hisilicon Watchdog Timer: 0.01 initialized. default_margin=30 sec (nowayout= 0, nodeamon= 1)
hi_i2c init is ok!
(none) login: *** Board tools : ver0.0.1_20120501  *** 
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x20030030: 0x00000000 --> 0x00000001 
reset sensor ov9712 finish ...
*** Board tools : ver0.0.1_20120501  *** 
[debug]: {source/utils/cmdshell.c:166}cmdstr:himm
0x20030030: 0x00000001 --> 0x00000005 
reset sensor ar0130 finish ...
hi3518_detect_sensor_type():  hi3518c_detect_sensor_type(): get ar0130 sensor, GPIO0_7=0
detected sensor type is 3
Hisilicon Media Memory Zone Manager
hi3518_base: module license 'Proprietary' taints kernel.
Disabling lock debugging due to kernel taint
Hisilicon UMAP device driver interface: v3.00
pa:84a00000, va:c5200000
load sys.ko for Hi3518...OK!
load viu.ko for Hi3518...OK!
ISP Mod init!
load vpss.ko ....OK!
load vou.ko ....OK!
load venc.ko for Hi3518...OK!
load group.ko for Hi3518...OK!
load chnl.ko for Hi3518...OK!
load h264e.ko for Hi3518...OK!
load jpege.ko for Hi3518...OK!
load rc.ko for Hi3518...OK!
load region.ko ....OK!
load vda.ko ....OK!
hi_i2c init is ok!
Kernel: ssp initial ok!
acodec inited!
insert audio
==== Your input Sensor type is ar0130 ====
sys_montor enter main loop...
tcp_mon start main loop...
encode_mon enter main loop...
sys_daemon mount /dev/mtdblock2 success
sys_daemon disable console
ADDRCONF(NETDEV_UP): eth0: link is not ready
Set IR-CUT default
get cmd to enable adc printk
i=1, curVol=0x1e, tmpVOL=0x153, ircutMode=1, ircutStatus=0
PHY: himii:01 - Link is Up - 100/Full
ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready

Login timed out after 60 seconds
IPNC login: