Let’s go!

  • sensehat i2c led2472g

    I2C에 연결된 LED Matrix 밝기 제어

    sensehat 모듈에 LED matrix가 i2c로 설치, 연결되어 있다. LED2472G가 각 연결된 LED를 제어하는데, AVR이 i2c로 라즈베리 파이와 LED2472G 를 중계한다. LED를 제어한다고 LED2472G datasheet를 찾으면 별 도움이 안된다. AVR로 led를 어떻게 제어하는지 잘 공개되지 않은 듯 하다. 아무리 찾아도 c로 작성한 코드를 찾을 수 없다. i2c 0x46에 0~191까지 밝기를 전송하면 led 밝기를 제어할 수 있다. 아래 game of life python 코드를 보면 대충 어떻게 돌아가는지 알 수 있다.

    shell로 i2cset으로 한 개씩 램프를 껐다. 0x46번은 LED matrix 노드 번이고, 0 ~ 191까지 led 램프 위치를 말하는 듯 하다. 뒤에 255, 0은 밝기다. 컬러 코드를 넣는 방법이 있는데, 아직 잘 모르겠다.

    pi@raspberrypi:~/rasp/sense_temperature $ i2cset 1 0x46 1 255
    WARNING! This program can confuse your I2C bus, cause data loss and worse!
    I will write to device file /dev/i2c-1, chip address 0x46,
    data address 0x01, data 0xff, mode byte.
    Continue? [Y/n] y
    pi@raspberrypi:~/rasp/sense_temperature $ i2cset 1 0x46 1 0
    WARNING! This program can confuse your I2C bus, cause data loss and worse!
    I will write to device file /dev/i2c-1, chip address 0x46,
    data address 0x01, data 0x00, mode byte.
    Continue? [Y/n] y
    pi@raspberrypi:~/rasp/sense_temperature $ i2cdetect 1
    WARNING! This program can confuse your I2C bus, cause data loss and worse!
    I will probe file /dev/i2c-1.
    I will probe address range 0x08-0x77.
    Continue? [Y/n] y
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00:                         -- -- -- -- -- -- -- -- 
    10: -- -- -- -- -- -- -- -- -- -- -- -- 1c -- -- -- 
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    40: -- -- -- -- -- -- 46 -- -- -- -- -- -- -- -- -- 
    50: -- -- -- -- -- -- -- -- -- -- -- -- 5c -- -- 5f 
    60: -- -- -- -- -- -- -- -- -- -- 6a -- -- -- -- -- 
    70: -- -- -- -- -- -- -- --                   

    shell로 0부터 191까지 해보면 led가 꺼지지 않는데 루프를 만들어 돌리면 한 번에 꺼진다. 구매 5일만에 led를 껐다.

    고수는 frame buffer를 만들어서 하는 것 같은데, 아직 잘 모르겠다. 정말 필요한지도 모르겠다.

    참조 사이트

  • sensehat i2c hts221

    HTS221 temperature conversion

    데이터 시트에 수식을 정확하게 써야지, linear interpolation을 머 이리 어렵게 썼는지.. U가 or 같은데, 정확하게 어떤 의미로 썼는지 모르겠다.

    하. T0_DegC, T_DegC, T1_DegC, T0_OUT, T_OUT, T1_OUT을 모두 확인 한 후에 위 그래프로 알아서 구하라는 말이었다. 미친!!!

    위 식대로 하면 172도를 볼 수 있다. stack overflow에 있듯이 T0_degC, T1_degC가 10비트임을 인식해야 한다. T0T1MSB에 있는 나머지 2비트를 읽어 내야 한다. datasheet를 보통 이렇게 쓰는지, 너무 불친절하다.

    위 그림 Step1은 결국 10비트를 만들어서 8로 나누란 말이다. 두 값으로 interpolation 하여 구하란 의미다. 이걸 누가 알아 듣냐고!! 대략 아래 코드로 온도를 알아낼 수 있다. 대략 25도 나오는데, 맞는 듯 하다.

    https://github.com/now0930/sensehat_toy

    참조 사이트

  • unkown symbol

    insmod 실행 시 unknown symbol 에러

    가끔 모듈을 컴파일 하여 insmod로 추가할 때 unknown symbol 에러로 추가가 안 될 경우가 있다. xpad.c를 따라할 때 해당 함수를 찾아 지우고 했지만, 이번 sensehat을 사용하려는 기본 함수는 지울 수 없어 이유를 찾아야 했다.

    [ 8890.395611] sensehat_core: loading out-of-tree module taints kernel.
    [ 8890.395805] sensehat_core: Unknown symbol __devm_regmap_init_i2c (err -2)
    [ 8903.630685] sensehat_core: Unknown symbol __devm_regmap_init_i2c (err -2)
    [ 9094.432329] sensehat_core: Unknown symbol __devm_regmap_init_i2c (err -2)
    [ 9232.390045] sensehat_core: Unknown symbol __devm_regmap_init_i2c (err -2)

    결과적으로 devm_regmap_init_i2c를 사용하려면 먼저 regmap_i2c를 로딩해야 하는데, 이 작업을 하지 않아 그렇다. 부팅한 버전과 일치하는regmap-i2c.ko를 찾아 insmod regmap-i2c.ko로 먼저 로딩해야 한다.

    어떤 모듈이 미리 필요한지 알기 위해서는 해당 모듈을 lib/modules/”부팅버전”에 복사하고 depmod -a로 의존성 확인을 먼저 해야 한다. modprobe로 내가 원하는 모듈을 로딩하면 의존성을 확인하여 같이 로딩한다.

    매번 수정되는 드라이버를 modprobe로 로딩하기 귀찮으니, 해당 파일이 부팅 때 자동으로 로딩 되도록 수정한다.

    pi@raspberrypi:/etc/modules-load.d $ pwd
    /etc/modules-load.d
    pi@raspberrypi:/etc/modules-load.d $ cat modules.conf 
    # /etc/modules: kernel modules to load at boot time.
    #
    # This file contains the names of kernel modules that should be loaded
    # at boot time, one per line. Lines beginning with "#" are ignored.
    
    i2c-dev
    #sensehat_core를 사용하기 위한 모듈 선 로딩
    regmap_i2c

    이제 sensehat을 가지고 놀 준비가 되었다.

  • linux pages

    Pages

    연속된 메모리를 할당을 테스트 했다. dmes로 보면 어느 정도 출력하다 끊어 버린다. 마지막 데이터를 확인 했다.

    #include<linux/kernel.h>
    #include<linux/init.h>
    #include<linux/module.h>
    #include <linux/slab.h>
    #include <linux/mempool.h>
    
    #define PAGES_ORDER 2
    
    char* data;
    static int __init hello_world_init(void) /* Constructor */
    {
    	printk(KERN_INFO "hello, pages\n");
    	/* memory 할당*/
    	data = (char*)__get_free_pages(GFP_KERNEL, PAGES_ORDER);
    	if (!data){
    		printk("no pages allocated\n");
    		return ENOMEM;
    	}
    	/* 0으로 초기화*/
    	memset(data, 'c', PAGE_SIZE << PAGES_ORDER); 
    	printk(KERN_INFO "data: pos:%p, size: %0xd, %d\n", data, (int)(PAGE_SIZE << PAGES_ORDER), data[(PAGE_SIZE << PAGES_ORDER)-1]);
    	return 0;
    }
    
    void __exit hello_world_exit(void)
    {
    	printk(KERN_INFO "good bye, pages\n");
    	free_pages((unsigned long)data, PAGES_ORDER);
    
    }
    module_init(hello_world_init);
    module_exit(hello_world_exit);
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("now0930");
    MODULE_DESCRIPTION("pages test");
    pi@raspberrypi:~/rasp/advancedMemory/pages $ dmesg | tail -10
    [ 1104.594762] hello, pages
    [ 1104.594802] data: pos:c32289cc, size: 4000d, 99
    [ 1122.403587] good bye, pages
  • linux memory pools

    memory pools

    cache memory에 이어 memory pools를 실습했다. 역시 책만 보면 잘 모른다. nvme 드라이버- drivers/nvme/target/io-cmd-file.c – 중 mempool 관련 코드를 찾을 수 있다.

    #include<linux/kernel.h>
    #include<linux/init.h>
    #include<linux/module.h>
    #include <linux/slab.h>
    #include <linux/mempool.h>
    
    #define scullc_quantum 16
    /* declare one cache pointer: use it for all devices */
    /* kmem_cache_t 가 kmem_cache로 변경됨*/
    struct kmem_cache *scullc_cache;
    static const char test[scullc_quantum]="123456789abcde";
    static char* data;
    mempool_t *mem_pool1;
    static int __init hello_world_init(void) /* Constructor */
    {
    	int i;
    	printk(KERN_INFO "hello, pool memory\n");
    	/* memory 할당*/
    	scullc_cache = kmem_cache_create("scullc", scullc_quantum*sizeof(char),
    			0, SLAB_HWCACHE_ALIGN, NULL); /* no ctor */
    
    	if (!scullc_cache) {
    		printk(KERN_ERR "no memory. out.\n");
    		return -ENOMEM;
    
    	}
    	
    	/* memory pool로 allocate*/
    	mem_pool1 = mempool_create(16, mempool_alloc_slab, mempool_free_slab,
    			scullc_cache);
    
    	//data = kmem_cache_alloc(scullc_cache, GFP_KERNEL);
    
    	data = mempool_alloc(mem_pool1, GFP_KERNEL);
    	for (i=0;i<scullc_quantum;i++){
    		data[i] = test[i];
    	}
    
    	printk(KERN_INFO "cache: pos: %p, size: %d\n",scullc_cache, sizeof(scullc_cache));
    	printk(KERN_INFO "data: pos:%p, size: %d, %s\n",data, sizeof(data), data);
    	return 0;
    }
    
    void __exit hello_world_exit(void)
    {
    	//kmem_cache_free(scullc_cache, data);
    	mempool_free(data, mem_pool1);
    	mempool_destroy(mem_pool1);
    	kmem_cache_destroy(scullc_cache);
    	printk(KERN_INFO "good bye, pool memory\n");
    
    }
    module_init(hello_world_init);
    module_exit(hello_world_exit);
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("now0930");
    MODULE_DESCRIPTION("cache memory test");
    pi@raspberrypi:~/rasp/advancedMemory/mempool $ make
    #make -C /lib/modules/5.10.63-v7l+/build V=1 M=/home/pi/rasp/advancedMemory/mempool modules
    make -C /lib/modules/`uname -r`/build M=`pwd` modules
    make[1]: 디렉터리 '/usr/src/linux-headers-5.10.63-v7l+' 들어감
    make[1]: 디렉터리 '/usr/src/linux-headers-5.10.63-v7l+' 나감
    pi@raspberrypi:~/rasp/advancedMemory/mempool $ sudo insmod memory_pool.ko
    pi@raspberrypi:~/rasp/advancedMemory/mempool $ sudo rmmod memory_pool 
    pi@raspberrypi:~/rasp/advancedMemory/mempool $ dmesg | tail -10
    [52590.309504] hello, pool memory
    [52590.309579] cache: pos: 0c17faff, size: 4
    [52590.309598] data: pos:f97bc0b2, size: 4, 123456789abcde
    [52601.784069] good bye, pool memory