From 7f46bd3940b619b45a4ef6f97157a47b861149a5 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Tue, 31 Mar 2026 16:01:33 +0200 Subject: [PATCH] refactor(lab02): split exercices for skeleton --- src/01-skeleton/s02e02-parameters.c | 15 ++ src/01-skeleton/s02e04-dynamic_allocation.c | 56 +++++++ src/01-skeleton/s02e05-io_memory_mapped.c | 105 +++++++++++++ src/01-skeleton/skeleton.c | 156 +++----------------- 4 files changed, 199 insertions(+), 133 deletions(-) create mode 100644 src/01-skeleton/s02e02-parameters.c create mode 100644 src/01-skeleton/s02e04-dynamic_allocation.c create mode 100644 src/01-skeleton/s02e05-io_memory_mapped.c diff --git a/src/01-skeleton/s02e02-parameters.c b/src/01-skeleton/s02e02-parameters.c new file mode 100644 index 0000000..15298bd --- /dev/null +++ b/src/01-skeleton/s02e02-parameters.c @@ -0,0 +1,15 @@ +#include // needed by all modules +#include // needed for macros +#include // needed for debugging + +#include + +static char* text = "dummy text"; +module_param(text, charp, 0664); +static int elements = 1; +module_param(elements, int, 0); + +void parameters_print(void) { + pr_debug("text: %s\n", text); + pr_debug("elements: %d\n", elements); +} \ No newline at end of file diff --git a/src/01-skeleton/s02e04-dynamic_allocation.c b/src/01-skeleton/s02e04-dynamic_allocation.c new file mode 100644 index 0000000..f8591b8 --- /dev/null +++ b/src/01-skeleton/s02e04-dynamic_allocation.c @@ -0,0 +1,56 @@ +#include // needed by all modules +#include // needed for macros +#include // needed for debugging + +#include // dynamic memory allocation +#include // linked list +#include + +#define TEXT_LENGTH_MAX 255 + +struct element { + char text[TEXT_LENGTH_MAX]; + int32_t unique_number; + struct list_head node; +}; + +static LIST_HEAD (list_unique_elements); + +void dynAlloc_init(void) { + pr_info("Initialize dynamic allocation and linked list\n"); + + struct element* element_ptr = kcalloc(elements, sizeof(struct element), GFP_KERNEL); + if (element_ptr == 0) { + pr_err("Failed to allocate memory for %d elements\n", elements); + return; + } + + uint8_t i; + const uint8_t length = TEXT_LENGTH_MAX - 1; + for (i = 0; i < elements; i++) { + struct element* e = element_ptr + i; + if (e != 0) { + strncpy(e->text, text, length); + e->unique_number = i; + list_add_tail(&e->node, &list_unique_elements); + pr_info ("add element %d: %s\n", e->unique_number, e->text); + } + } + + pr_info("Dynamic allocation and linked list initialized\n"); +} + +void dynAlloc_exit(void) { + pr_info("Free memory allocated for dynamic allocation and linked list\n"); + + struct element* e; + + while (!list_empty(&list_unique_elements)) { + e = list_entry(list_unique_elements.next, struct element, node); + pr_info ("delete element %d: %s\n", e->unique_number, e->text); + list_del(&e->node); + kfree(e); + } + + pr_info("Memory allocated for dynamic allocation and linked list freed\n"); +} \ No newline at end of file diff --git a/src/01-skeleton/s02e05-io_memory_mapped.c b/src/01-skeleton/s02e05-io_memory_mapped.c new file mode 100644 index 0000000..e9ea9e9 --- /dev/null +++ b/src/01-skeleton/s02e05-io_memory_mapped.c @@ -0,0 +1,105 @@ +#include // needed by all modules +#include // needed for macros +#include // needed for debugging + +#include +#include + +#define CHIP_ID_BASE_ADDR 0x01c14000 +#define TEMPERATURE_SENSOR_BASE_ADDR 0x01C25000 +#define ETHERNET_CONTROLLER_BASE_ADDR 0x01C30000 + +static struct resource* resources[3] = {[0] = 0,}; + +void ioMemoryMapped_init(void) { + pr_info("Initialize memory-mapped I/O\n"); + + // Declare variables + unsigned char* registers[3] = {[0] = 0,}; + uint32_t chipid[4] = {[0] = 0,}; + uint32_t temperature = 0; + uint32_t mac_address[2] = {[0] = 0,}; + + // Request memory + resources[0] = request_mem_region(CHIP_ID_BASE_ADDR, 0x1000, "nanopi - chip ID"); + if (resources[0] == 0) { + pr_info("Failed to reserve memory region for chip ID\n"); + } + + resources[1] = request_mem_region(TEMPERATURE_SENSOR_BASE_ADDR, 0x1000, "nanopi - temperature sensor"); + if (resources[1] == 0) { + pr_info("Failed to reserve memory region for temperature sensor\n"); + } + + resources[2] = request_mem_region(ETHERNET_CONTROLLER_BASE_ADDR, 0x1000, "nanopi - Ethernet controller"); + if (resources[2] == 0) { + pr_info("Failed to reserve memory region for Ethernet controller\n"); + } + + + // Map memory + registers[0] = ioremap(CHIP_ID_BASE_ADDR, 0x1000); + if (registers[0] == 0) { + pr_err("Failed to map processor registers for chip ID\n"); + return; + } + registers[1] = ioremap(TEMPERATURE_SENSOR_BASE_ADDR, 0x1000); + if (registers[1] == 0) { + pr_err("Failed to map processor registers for temperature sensor\n"); + return; + } + + registers[2] = ioremap(ETHERNET_CONTROLLER_BASE_ADDR, 0x1000); + if (registers[2] == 0) { + pr_err("Failed to map processor registers for Ethernet controller\n"); + return; + } + + + // Read values - Chip ID + chipid[0] = ioread32(registers[0] + 0x200); + chipid[1] = ioread32(registers[0] + 0x204); + chipid[2] = ioread32(registers[0] + 0x208); + chipid[3] = ioread32(registers[0] + 0x20c); + pr_info( + "chipid=%08x'%08x'%08x'%08x\n", + chipid[0], chipid[1], chipid[2], chipid[3] + ); + + // Read values - Temperature + temperature = -1991 * (int32_t) ioread32(registers[1] + 0x80) / 10 + 223000; + pr_info( + "temperature=%d (register value: %d)\n", + temperature, ioread32(registers[1] + 0x80) + ); + + // Read values - MAC address + mac_address[0] = ioread32(registers[2] + 0x50); + mac_address[1] = ioread32(registers[2] + 0x54); + pr_info( + "mac-addr=%02x:%02x:%02x:%02x:%02x:%02x\n", + (mac_address[1] >> 0) & 0xff, + (mac_address[1] >> 8) & 0xff, + (mac_address[1] >> 16) & 0xff, + (mac_address[1] >> 24) & 0xff, + (mac_address[0] >> 0) & 0xff, + (mac_address[0] >> 8) & 0xff + ); + + // Unmap memory + iounmap(registers[0]); + iounmap(registers[1]); + iounmap(registers[2]); + + pr_info("Memory-mapped I/O initialized\n"); + +} + +void ioMemoryMapped_exit(void) { + pr_info("Free memory-mapped I/O\n"); + + // Release memory + if (resources[0] != 0) release_mem_region(CHIP_ID_BASE_ADDR, 0x1000); + if (resources[1] != 0) release_mem_region(TEMPERATURE_SENSOR_BASE_ADDR, 0x1000); + if (resources[2] != 0) release_mem_region(ETHERNET_CONTROLLER_BASE_ADDR, 0x1000); +} \ No newline at end of file diff --git a/src/01-skeleton/skeleton.c b/src/01-skeleton/skeleton.c index 1c42905..e2b690d 100644 --- a/src/01-skeleton/skeleton.c +++ b/src/01-skeleton/skeleton.c @@ -3,156 +3,46 @@ #include // needed for macros #include // needed for debugging -#include // needed for module parameters - -#include // dynamic memory allocation -#include // linked list -#include - -#include -#include - - -#define TEXT_LENGTH_MAX 255 - -#define CHIP_ID_BASE_ADDR 0x61c14000 -#define TEMPERATURE_SENSOR_BASE_ADDR 0x61C25000 -#define ETHERNET_CONTROLLER_BASE_ADDR 0x61C30000 - - -static char* text = "dummy text"; -module_param(text, charp, 0664); -static int elements = 1; -module_param(elements, int, 0); - - -// Ex04 - Dynamic memory allocation and linked list -struct element { - char text[TEXT_LENGTH_MAX]; - int32_t unique_number; - struct list_head node; -}; - -static LIST_HEAD (list_unique_elements); - - -// Ex05 - Memory-mapped I/O -static struct resource* resources[3] = {[0] = 0,}; +#include "s02e02-parameters.c" +#include "s02e04-dynamic_allocation.c" +#include "s02e05-io_memory_mapped.c" static int __init skeleton_init(void) { - pr_info("Linux module skeleton ex05 loaded\n"); - pr_debug(" text: %s\n elements: %d\n", text, elements); - + pr_info("Linux module skeleton ex05 loading...\n"); + pr_info("--------------------\n"); - // Ex04 - Dynamic memory allocation and linked list - struct element* element_ptr = kcalloc(elements, sizeof(struct element), GFP_KERNEL); - if (element_ptr == 0) { - pr_err("Failed to allocate memory for %d elements\n", elements); - return -ENOMEM; - } - - uint8_t i; - const uint8_t length = TEXT_LENGTH_MAX - 1; - for (i = 0; i < elements; i++) { - struct element* e = element_ptr + i; - if (e != 0) { - strncpy(e->text, text, length); - e->unique_number = i; - list_add_tail(&e->node, &list_unique_elements); - pr_info ("add element %d: %s\n", e->unique_number, e->text); - } - } + // Lab02 - Exercise 2: Parameters + parameters_print(); - // Ex05 - Memory-mapped I/O - unsigned char* registers[3] = {[0] = 0,}; - uint32_t chipid[4] = {[0] = 0,}; - uint32_t temperature = 0; - uint32_t mac_address[2] = {[0] = 0,}; + pr_info("--------------------\n"); - resources[0] = request_mem_region(CHIP_ID_BASE_ADDR, 0x1000, "nanopi - chip ID"); - resources[1] = request_mem_region(TEMPERATURE_SENSOR_BASE_ADDR, 0x1000, "nanopi - temperature sensor"); - resources[2] = request_mem_region(ETHERNET_CONTROLLER_BASE_ADDR, 0x1000, "nanopi - Ethernet controller"); - if (resources[0] == 0) { - pr_err("Failed to reserve memory region for chip ID\n"); - return -EFAULT; - } - if (resources[1] == 0) { - pr_err("Failed to reserve memory region for temperature sensor\n"); - return -EFAULT; - } - if (resources[2] == 0) { - pr_err("Failed to reserve memory region for Ethernet controller\n"); - return -EFAULT; - } + // Lab02 - Exercise 4: Dynamic memory allocation and linked list + dynAlloc_init(); - registers[0] = ioremap(CHIP_ID_BASE_ADDR, 0x1000); - registers[1] = ioremap(TEMPERATURE_SENSOR_BASE_ADDR, 0x1000); - registers[2] = ioremap(ETHERNET_CONTROLLER_BASE_ADDR, 0x1000); - if (registers[0] == 0) { - pr_err("Failed to map processor registers for chip ID\n"); - return -EFAULT; - } - if (registers[1] == 0) { - pr_err("Failed to map processor registers for temperature sensor\n"); - return -EFAULT; - } - if (registers[2] == 0) { - pr_err("Failed to map processor registers for Ethernet controller\n"); - return -EFAULT; - } + pr_info("--------------------\n"); - chipid[0] = ioread32(registers[0] + 0x200); - chipid[1] = ioread32(registers[0] + 0x204); - chipid[2] = ioread32(registers[0] + 0x208); - chipid[3] = ioread32(registers[0] + 0x20c); - pr_info( - "chipid=%08x'%08x'%08x'%08x\n", - chipid[0], chipid[1], chipid[2], chipid[3] - ); - - temperature = -1991 * (int32_t) ioread32(registers[1] + 0x80) / 10 + 223000; - pr_info( - "temperature=%d (register value: %d)\n", - temperature, ioread32(registers[1] + 0x80) - ); - - mac_address[0] = ioread32(registers[2] + 0x50); - mac_address[1] = ioread32(registers[2] + 0x54); - pr_info( - "mac-addr=%02x:%02x:%02x:%02x:%02x:%02x\n", - (mac_address[1] >> 0) & 0xff, - (mac_address[1] >> 8) & 0xff, - (mac_address[1] >> 16) & 0xff, - (mac_address[1] >> 24) & 0xff, - (mac_address[0] >> 0) & 0xff, - (mac_address[0] >> 8) & 0xff - ); - - iounmap(registers[0]); - iounmap(registers[1]); - iounmap(registers[2]); + // Lab02 - Exercise 5: Memory-mapped I/O + ioMemoryMapped_init(); + pr_info("--------------------\n"); + pr_info("Linux module skeleton loaded\n"); return 0; } static void __exit skeleton_exit(void) { - // Ex04 - Dynamic memory allocation and linked list - struct element* e; + + // Lab02 - Exercise 4: Dynamic memory allocation and linked list + dynAlloc_exit(); - while (!list_empty(&list_unique_elements)) { - e = list_entry(list_unique_elements.next, struct element, node); - pr_info ("delete element %d: %s\n", e->unique_number, e->text); - list_del(&e->node); - kfree(e); - } + pr_info("--------------------\n"); - // Ex05 - Memory-mapped I/O - if (resources[0] != 0) release_mem_region(CHIP_ID_BASE_ADDR, 0x1000); - if (resources[1] != 0) release_mem_region(TEMPERATURE_SENSOR_BASE_ADDR, 0x1000); - if (resources[2] != 0) release_mem_region(ETHERNET_CONTROLLER_BASE_ADDR, 0x1000); + // Lab02 - Exercise 5: Memory-mapped I/O + ioMemoryMapped_exit(); + + pr_info("--------------------\n"); pr_info ("Linux module skeleton unloaded\n"); }