顯示具有 Programming 標籤的文章。 顯示所有文章
顯示具有 Programming 標籤的文章。 顯示所有文章

2024年8月4日 星期日

Experience of STM32

STM32MP157A-DK1

ST-LINK v2

    VCOM

        Baud = 115200bps



2024年5月10日 星期五

Handbook - ubus

/ # ubus call SIMAgent lst

{

        "tot": true,

        "cnt": true,

        [

                {

                        "cls": false,

                        "stt": false,

                        "cid": "98000000000000000021",

                        "spn": "Rohde & Schwarz",

                        "nam": "R&S CMW500 3G_XOR"

                }

        ],

        "res": 0

}

 

2024年5月2日 星期四

高內聚,低耦合 (high cohesion、low coupling)

Source 中鳥階段-高內聚,低耦合。 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

高內聚,低耦合 (high cohesion、low coupling) 的意思是,物件的程式碼應該要有很高的比率只和物件內其他有關的程式碼有關聯,而對外部的程式碼,物件或元件等的關聯度要愈低愈好 (最佳的狀態是零耦合)。這樣做的用意是讓物件可以獨立的發展,而無須依賴外部的任何程式碼,如此一來,物件本身可以在不影響其他程式的情況下自由的修改與變化,而外部程式的任何修改也不會影響到物件本身的功能與運作。

2023年12月29日 星期五

RESTful design

ChatGPT answers "What does RESTful design refer to?":

RESTful design, or Representational State Transfer, is an architectural style for designing networked applications. It was introduced by Roy Fielding in his doctoral dissertation in 2000. REST is not a protocol but rather a set of constraints and principles that, when applied to a system, help create scalable, maintainable, and loosely coupled web services.

Here are the key principles of RESTful design:

  1. Stateless Communication:

    • Each request from a client to a server must contain all the information needed to understand and fulfill the request. The server should not store any information about the client between requests. Each request from a client to a server must contain all the information needed to understand and fulfill the request.
  2. Client-Server Architecture:

    • The client and server are separate entities that communicate over a network. The client is responsible for the user interface and user experience, while the server is responsible for processing requests, managing resources, and handling business logic.
  3. Uniform Interface:

    • RESTful APIs should have a consistent and uniform interface. This principle is further divided into several constraints:
      • Resource Identification: Resources (such as data objects or services) are identified by URIs (Uniform Resource Identifiers).
      • Resource Manipulation through Representations: Resources are manipulated using representations, and these representations can be in various formats (e.g., JSON, XML).
      • Self-Descriptive Messages: Each message from the server to the client should include enough information to describe how to process the message.
      • Hypermedia as the Engine of Application State (HATEOAS): Clients interact with the application entirely through hypermedia provided dynamically by the application servers.
  4. Stateless Communication:

    • Each request from a client to a server must contain all the information needed to understand and fulfill the request. The server should not store any information about the client between requests.
  5. Cacheability:

    • Responses from the server can be explicitly marked as cacheable or non-cacheable. This improves efficiency and scalability by allowing clients to cache responses.
  6. Layered System:

    • A client cannot ordinarily tell whether it is connected directly to the end server or to an intermediary along the way. Intermediary servers (proxies, gateways, etc.) can be added to improve scalability or enforce security without impacting the client.

RESTful design is commonly used in the development of web services, including APIs (Application Programming Interfaces) for IoT devices, web applications, and mobile applications. It emphasizes simplicity, scalability, and the decoupling of components, making it a popular choice for building distributed systems on the web.

2023年12月17日 星期日

Linux pipe

Q: How to process input pipe in real time?
A: Linux pipe is buffered (4096? 65536? bytes)
     Solution#1:
Unix buffering delays output to stdout, ruins your day | TurnKey GNU/Linux (turnkeylinux.org)
fflush(stdout);
     Solution#2:

2023年9月30日 星期六

SOLID programming rule

非禮勿動 / 透過被允許的介面操作機器 (方向盤/油門 rather than 噴油參數 w/ 檔位 ignored)
Polymorphism/Callback: function pointer --> 舊瓶裝新酒
Method vs data

SOLID refers to
S: Single Responsibility Principle
A code snippet of same logic is implemented more than once, make it a standalone function.
O: Open Close Principle
L: Liskov Substitution Principle
I: Interface Segregation Principle
D:*Dependency Inversion Principle

2023年8月20日 星期日

Linux module programming

Source module_platform_driver 與 module_init_module_platform_driver module_init_嵌入式小胖的博客-CSDN博客

module_platform_driver 與 module_init


版權聲明:本文為CSDN博主「嵌入式小胖」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本聲明。
原文連結:https://blog.csdn.net/m0_37765662/article/details/106490792

在linux內核源碼中,我們經常看到module_platform_driver 與 module_init這兩個宏定義,有時候在這個驅動中用module_platform_driver,有時候用module_init,那這兩個宏定義之間有什麼差異嗎? 還是說可以隨便用呢? 這就需要我們旭跟蹤代碼,來看看這兩個宏定義到底什麼東西?

首先,介紹下
module_initmodule_init對於做驅動的人應該不陌生,linux內核是一個巨集內核,巨集內核就是驅動和內核打包在一起的。 由於驅動是作為內核模組掛載在內核上的,而內核對於模組的介面就是module_initmodule_exit,所以你要載入一個內核模組的時候,必須使用module_init來進行,而卸載一個內核模組的時候,必須使用module_exit來進行。 例如:

 

module_init(xxxx_init); 載入xxxx模組

 

module_exit(xxxx_exit); 卸載xxxx模組

 

那是不是就有一個疑問了,既然是所有模組都是通過這兩個函數來進行載入和卸載的,那應該所有驅動都用module_init函數啊,為什麼還會有module_platform_driver 這不是多此一舉嗎? 醒醒吧,少年,Linux社區那麼多大神在更新,會出現這種錯誤嗎?

 

那麼我們先看看module_platform_driver的宏定義是個啥?

 

#define module_platform_driver(__platform_driver) \

            module_driver(__platform_driver, platform_driver_register, \

                                    platform_driver_unregister)

#define module_driver(__driver, __register, __unregister, ...) \

static int __init __driver##_init(void) \

{ \

            return __register(&(__driver) , ##__VA_ARGS__); \

} \

module_init(__driver##_init); \

static void __exit __driver##_exit(void) \

{ \

            __unregister(&(__driver) , ##__VA_ARGS__); \

} \

module_exit(__driver##_exit);

從代碼中看到,module_platform_driver 追根溯源,發現最終還是調用了module_init,但是,又不僅僅是調用了module_init,還調用了platform_driver_registerplatform_driver_unregister,這兩個函數的作用就是註冊和卸載平臺驅動。

 

一般某個設備或某個控制器掛載在處理器上時,肯定是通過某種總線來連接的,比喻說常見總線有SPI總線、IIC總線等等,但控制器一般是通過內部總線掛載處理器端的,對於這一類設備,linux抽象出了一個平臺總線,來包含所有的處理器總線掛載的設備。 而這類總線需要註冊到內核中去,就需要用platform_driver_register來實現,平臺總線是抽象出來的,所以所有通過總線直接連在處理器上的設備是不需要關心平臺總線怎麼運作的,因此這個平臺總線的註冊和註銷都是通用的,所以在載入總線設備驅動時,直接調用module_platform_driver 就可以將平臺驅動註冊函數和卸載函數、以及總線設備載入一次性運行完,避免了總線驅動在每次載入驅動時都需要手動註冊平臺總線。

 

其實說了這麼多,module_platform_driver就是對module_init進一步的封裝,在module_init之外添加了一些功能,對於平臺總線設備而言,直接調用module_platform_driver就可以避免在module_init函數中去註冊平臺驅動了,使得平臺設備驅動的載入變得更方便了。

 

那是不是說module_init可以與module_platform_driver就可以通用呢? 當然不是,能用module_platform_driver的地方肯定可以用module_init,但能用module_init卻不一定能用module_platform_driver,這主要看設備是不是通過平臺總線的方式掛載處理器上的。

 

函數名            非平臺總線設備        平臺總線設備

module_platform_driver        不可用            可用

module_init     可用    可用

對於平臺總線設備,可以用兩種方法來載入

 

static int __init xxxx_init(void)

{

            return platform_driver_register(&xxxx_driver);

}

 

static void __exit xxxx_exit(void)

{

            platform_driver_unregister(&xxxx_driver);

}

 

module_init(xxxx_init);

module_exit(xxxx_exit);

module_platform_driver(xxxx_driver);

這兩種方式的效果是一樣的,但明顯module_platform_driver比較簡潔。

 

但對於其他總線的設備,就不能使用module_platform_driver了,必須使用module_init,在module_init函數中再註冊一遍其他總線,例如SPI總線設備。

 

static int __init spidev_init(void)

{

            int status;

 

            /* Claim our 256 reserved device numbers.  Then register a class

             * that will key udev/mdev to add/remove /dev nodes.  Last, register

             * the driver which manages those device numbers.

             */

            BUILD_BUG_ON(N_SPI_MINORS > 256);

            status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);

            if (status < 0)

                        return status;

 

            spidev_class = class_create(THIS_MODULE, "spidev");

            if (IS_ERR(spidev_class)) {

                        unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);

                        return PTR_ERR(spidev_class);

            }

 

            status = spi_register_driver(&spidev_spi_driver);

            if (status < 0) {

                        class_destroy(spidev_class);

                        unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);

            }

            return status;

}

module_init(spidev_init);

 

static void __exit spidev_exit(void)

{

            spi_unregister_driver(&spidev_spi_driver);

            class_destroy(spidev_class);

            unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);

}

module_exit(spidev_exit);

 

還有一種情況不能使用module_platform_driver,就是我們編寫的驅動程式要使用之前某個驅動程式的功能時,就不能使用module_platform_driver,因為如果都使用module_platform_driver,內核編譯連結時,並不知道哪個驅動程式會被連結再前面,也就不知道哪個驅動程式會先執行,如果使用自訂的驅動(使用其他驅動程式功能的程式)先執行,而其他驅動還未進行初始化,就會出現難以預料的問題,所以這種情況下就必須使用late_initcall

————————————————



2023年3月22日 星期三

Identify floating point type of a Linux executable.

Ref: https://stackoverflow.com/questions/20555594/how-can-i-know-if-an-arm-library-is-using-hardfp

Execute readelf -A library.so: if the list of printed tags contains Tag_ABI_VFP_args: VFP registers, then it is a hardfp binary, otherwise assume softfp.

E.g. readelf -A /lib/arm-linux-gnueabihf/libm.so.6 will produce

Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "7-A"
  Tag_CPU_arch: v7
  Tag_CPU_arch_profile: Application
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-2
  Tag_FP_arch: VFPv3-D16
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int
  Tag_ABI_HardFP_use: SP and DP
  Tag_ABI_VFP_args: VFP registers
  Tag_ABI_optimization_goals: Aggressive Speed
  Tag_CPU_unaligned_access: v6

On the other side, readelf -A /lib/arm-linux-gnueabi/libm.so.6 produces

Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "7-A"
  Tag_CPU_arch: v7
  Tag_CPU_arch_profile: Application
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-2
  Tag_FP_arch: VFPv3-D16
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int
  Tag_ABI_optimization_goals: Aggressive Speed
  Tag_CPU_unaligned_access: v6