Embedded Software

  • STM32, CMake,GCC, VS Code

    Here is a stepwise guide to getting started with STM32 embeddedC programming using GCC, CMAKE, and Visual Studio Code IDE:

    1. Install the necessary tools:
    2. Create a new project:
      • Create a new directory for your project.
      • In the project directory, create a file named CMakeLists.txt. This file will contain the CMake build instructions for your project.
      • In the project directory, create a file named main.c. This file will contain your main program code.
    3. Configure CMake:
      • Open Visual Studio Code and open the project directory.
      • Install the CMake Tools extension by clicking on the Extensions icon on the left sidebar and searching for “CMake Tools”.
      • In the project directory, create a file named CMakeSettings.json. This file will contain the CMake configuration for your project.
      • In CMakeSettings.json, specify the toolchain file for the GCC Arm Embedded toolchain, the build type (Debug or Release), and the target architecture (e.g., Cortex-M4).
      • In CMakeLists.txt, specify the minimum required version of CMake, the project name, the C language standard, the source files (main.c), and the target architecture.
    4. Build and Flash the Project:
      • Build the project by opening the Command Palette (Ctrl+Shift+P) and selecting “CMake: Build”. This will generate the binary file for your project.
      • Flash the binary file to your STM32 microcontroller using a programming tool such as ST-Link or J-Link.
    5. Debug the Project:
      • Install the Cortex-Debug extension by clicking on the Extensions icon on the left sidebar and searching for “Cortex-Debug”.
      • Connect your STM32 microcontroller to your computer and open a debug session by clicking on the Debug icon on the left sidebar and selecting “Create a launch.json file”.
      • In launch.json, specify the GDB server executable and port, the binary file path, and the target architecture.
      • Start the debug session by clicking on the “Start Debugging” button.

    That’s it! You should now have a working STM32 embeddedC project using GCC, CMake, and Visual Studio Code IDE.

    Example CMakeLists.txt:

    cmake_minimum_required(VERSION 3.16)
    project(stm32_example C ASM)
    
    set(CMAKE_C_STANDARD 11)
    
    set(TOOLCHAIN_PREFIX "arm-none-eabi-")
    set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}gcc")
    set(CMAKE_ASM_COMPILER "${TOOLCHAIN_PREFIX}gcc")
    set(CMAKE_OBJCOPY "${TOOLCHAIN_PREFIX}objcopy")
    
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T${CMAKE_SOURCE_DIR}/STM32F446RETx_FLASH.ld")
    
    file(GLOB_RECURSE SOURCES "Src/*.c" "Drivers/STM32F4xx_HAL_Driver/Src/*.c")
    
    add_executable(${PROJECT_NAME}.elf ${SOURCES})
    set_target_properties(${PROJECT_NAME}.elf PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
    
    add_custom_target(${PROJECT_NAME}.hex
        COMMAND ${CMAKE_OBJCOPY} -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
        DEPENDS ${PROJECT_NAME}.elf
    )
    
    add_custom_target(${PROJECT_NAME}.bin
        COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
        DEPENDS ${PROJECT_NAME}.elf
    )
    
    

    In this example, we are toggling the LED connected to PA5 of the STM32F446RETx microcontroller every second.

    #include "stm32f4xx_hal.h"
    
    int main(void) {
        HAL_Init();
        __HAL_RCC_GPIOA_CLK_ENABLE();
        GPIO_InitTypeDef GPIO_InitStruct;
        GPIO_InitStruct.Pin = GPIO_PIN_5;
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        while (1) {
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
            HAL_Delay(1000);
        }
    }
    
    
  • Embedded C Interview Questions

    1. What is Embedded C? Embedded C is a programming language used to develop firmware or system software for embedded systems such as microcontrollers, microprocessors, and other programmable devices.
    2. What is the difference between C and Embedded C? The difference between C and Embedded C is that Embedded C is a subset of the C language. It is tailored to meet the specific requirements of embedded systems.
    3. What is the use of volatile keyword in Embedded C? The volatile keyword is used in Embedded C to indicate that a variable’s value may change at any time. This keyword is typically used with input/output (I/O) ports and memory-mapped registers.
    4. What is a pointer in Embedded C? A pointer in Embedded C is a variable that stores the memory address of another variable. Pointers are commonly used to access memory-mapped I/O registers and arrays.
    5. What is the difference between malloc() and calloc() functions in Embedded C? The difference between malloc() and calloc() functions in Embedded C is that malloc() allocates a block of memory of a specified size, while calloc() allocates a block of memory of a specified size and initializes all the memory to zero.
    6. What is an interrupt in Embedded C? An interrupt in Embedded C is a signal that is generated by a peripheral device or software that causes the CPU to stop its current execution and start executing a different program or function.
    7. What is the use of typedef in Embedded C? The typedef keyword in Embedded C is used to create a new data type by aliasing an existing data type. This can make code easier to read and maintain.
    8. What is a structure in Embedded C? A structure in Embedded C is a user-defined data type that groups related data items of different data types. Structures can be used to represent complex data structures such as linked lists and trees.
    9. What is a union in Embedded C? A union in Embedded C is a user-defined data type that allows different data types to share the same memory location. Unions are typically used to save memory when multiple data types need to be stored in the same memory location.
    10. What is the difference between a union and a structure in Embedded C? The difference between a union and a structure in Embedded C is that a union allows different data types to share the same memory location, while a structure groups related data items of different data types.
    11. What is the use of a bit field in Embedded C? A bit field in Embedded C is a group of bits within a data structure that is used to represent flags or other data items that require only a small number of bits. Bit fields are typically used to save memory.
    12. What is the use of #define in Embedded C? The #define directive in Embedded C is used to define a constant value or macro that can be used throughout the code. This can make the code more readable and maintainable.
    13. What is the difference between #define and const in Embedded C? The difference between #define and const in Embedded C is that #define creates a macro that replaces the defined value with its value throughout the code, while const creates a read-only variable that can be used like any other variable.
    14. What is the use of an enum in Embedded C? An enum in Embedded C is a user-defined data type that assigns a name to a set of integer values. Enums can be used to define constants or to represent options or states.
    15. What is the difference between a function and a macro in Embedded C? The difference between a function and a macro in Embedded C is that a function is a separate piece of code that can be called from different parts of the program, while a macro is a piece of code that is expanded inline by the preprocessor.
    16. What is the use of the static keyword in Embedded C? The static keyword in Embedded C is used to declare a variable or function that is visible only within the file where it is defined. This can help to prevent naming conflicts and make the code more modular.
    17. What is a watchdog timer in Embedded C? A watchdog timer in Embedded C is a hardware or software mechanism that resets the system if a program or process fails to respond within a certain amount of time. This can help to prevent system crashes and ensure reliable operation.
    18. What is the use of a semaphore in Embedded C? A semaphore in Embedded C is a synchronization mechanism that is used to control access to a shared resource such as a critical section or shared memory. Semaphores can help to prevent race conditions and ensure correct operation of the system.
    19. What is the use of a mutex in Embedded C? A mutex in Embedded C is a synchronization mechanism that is used to ensure exclusive access to a shared resource such as a critical section or shared memory. Mutexes can help to prevent race conditions and ensure correct operation of the system.
    20. What is the use of a timer in Embedded C? A timer in Embedded C is a hardware or software mechanism that generates an interrupt at a specified interval. Timers can be used for a variety of purposes such as measuring time, controlling system events, and generating PWM signals.
    21. What is the use of a counter in Embedded C? A counter in Embedded C is a hardware or software mechanism that increments a value at a specified interval. Counters can be used for a variety of purposes such as measuring time, counting events, and generating periodic signals.
    22. What is the use of a signal in Embedded C? A signal in Embedded C is a software interrupt that is generated by the operating system or another process. Signals can be used for a variety of purposes such as handling exceptions, interprocess communication, and controlling system events.
    23. What is the difference between polling and interrupt in Embedded C? The difference between polling and interrupt in Embedded C is that polling involves continuously checking a hardware or software condition in a loop, while interrupt involves waiting for a hardware or software event and handling it when it occurs.
    24. What is a real-time operating system (RTOS) in Embedded C? A real-time operating system (RTOS) in Embedded C is an operating system that is designed to provide deterministic and predictable behavior for real-time applications. RTOS typically provide features such as task scheduling, intertask communication, and memory management.
    25. What is the use of a heap in Embedded C? A heap in Embedded C is a region of memory that is used to allocate dynamic memory for data structures such as linked lists and trees. The heap is typically managed by the memory allocator such as malloc() or a custom memory management function.
    26. What is the use of a stack in Embedded C? A stack in Embedded C is a region of memory that is used to store local variables and function parameters. The stack is typically managed by the CPU or the compiler and can be used for efficient function call and return operations.
    27. What is the use of a linker in Embedded C? A linker in Embedded C is a software tool that is used to combine object files and libraries into an executable image that can be loaded and executed on the target system. The linker typically resolves dependencies, assigns memory addresses, and generates relocation information.
    28. What is the use of a cross-compiler in Embedded C? A cross-compiler in Embedded C is a compiler that runs on one platform but generates code for a different platform. Cross-compilers are typically used to develop software for embedded systems that have limited processing power and memory.
    29. What is the use of a simulator in Embedded C? A simulator in Embedded C is a software tool that is used to simulate the behavior of a target system or device. Simulators can be used to test and debug software without the need for physical hardware, and can provide a safe and controlled environment for testing.
    30. What is a linker script in Embedded C? A linker script in Embedded C is a file that is used to define the layout of the memory space for the target system. The linker script typically specifies the location and size of the code, data, and stack segments, as well as any custom memory regions or peripherals.
    31. What is a memory map in Embedded C? A memory map in Embedded C is a diagram or chart that shows the layout of the memory space for the target system. The memory map typically shows the location and size of the code, data, and stack segments, as well as any custom memory regions or peripherals.
    32. What is the use of a bootloader in Embedded C? A bootloader in Embedded C is a software program that is used to load and start the main application program on the target system. The bootloader typically provides a user interface for updating and configuring the firmware, and may also perform diagnostic and self-test functions.
    33. What is the use of a debugger in Embedded C? A debugger in Embedded C is a software tool that is used to test and debug software running on the target system. The debugger typically provides features such as code stepping, breakpoints, and memory inspection, and can help to identify and fix errors in the code.
    34. What is the use of an emulator in Embedded C? An emulator in Embedded C is a software tool that is used to simulate the behavior of the target hardware on a different platform, such as a personal computer. Emulators can be used to test and debug software without the need for physical hardware, and can provide a more realistic environment than a simulator.
    35. What is the use of a trace analyzer in Embedded C? A trace analyzer in Embedded C is a software tool that is used to capture and analyze the behavior of the target system during runtime. The trace analyzer typically provides features such as timing analysis, code profiling, and event logging, and can help to optimize the performance of the system.
    36. What is the use of a code profiler in Embedded C? A code profiler in Embedded C is a software tool that is used to measure and analyze the performance of the code running on the target system. The code profiler typically provides features such as execution time analysis, function call analysis, and memory usage analysis, and can help to identify and optimize performance bottlenecks.
    37. What is the use of an interrupt controller in Embedded C? An interrupt controller in Embedded C is a hardware device that is used to manage and prioritize interrupts from different sources on the target system. The interrupt controller typically provides features such as interrupt masking, nested interrupts, and interrupt prioritization, and can help to ensure reliable and efficient operation of the system.
    38. What is the use of a DMA controller in Embedded C? A DMA controller in Embedded C is a hardware device that is used to transfer data between different memory regions and peripherals on the target system. The DMA controller typically provides features such as burst mode, block transfers, and scatter-gather operations, and can help to offload data transfer tasks from the CPU.
    39. What is the use of a voltage regulator in Embedded C? A voltage regulator in Embedded C is a hardware device that is used to maintain a stable and regulated voltage supply for the target system. The voltage regulator typically provides features such as overcurrent protection, thermal shutdown, and adjustable output voltage, and can help to ensure reliable and efficient operation of the system.
    40. What is the use of a digital-to-analog converter (DAC) in Embedded C? A digital-to-analog converter (DAC) in Embedded C is a hardware device that is used to convert digital signals into analog signals. The DAC typically provides features such as resolution, output voltage range, and settling time, and can be used to generate analog waveforms for applications such as audio playback, motor control, and sensor interfacing.
    41. What is the use of a analog-to-digital converter (ADC) in Embedded C? An analog-to-digital converter (ADC) in Embedded C is a hardware device that is used to convert analog signals into digital signals. The ADC typically provides features such as resolution, sampling rate, and input voltage range, and can be used to digitize signals from sensors, audio inputs, and other analog sources.
    42. What is a driver in Embedded C? A driver in Embedded C is a software module that is used to interface with a specific hardware device or peripheral on the target system. The driver typically provides a set of functions and APIs that allow the application software to access and control the hardware device, and can help to abstract the low-level hardware details from the higher-level application code.
    43. What is a device driver in Embedded C? A device driver in Embedded C is a software module that is used to interface with a specific hardware device on the target system. The device driver typically provides a set of functions and APIs that allow the operating system or application software to access and control the hardware device, and can help to abstract the low-level hardware details from the higher-level software layers.
    44. What is a HAL in Embedded C? A HAL (Hardware Abstraction Layer) in Embedded C is a software module that is used to abstract the low-level hardware details of the target system from the higher-level application software. The HAL typically provides a set of functions and APIs that allow the application software to access and control the hardware devices and peripherals in a platform-independent manner.
    45. What is a BSP in Embedded C? A BSP (Board Support Package) in Embedded C is a software module that is used to provide the necessary software support for a specific hardware platform or board. The BSP typically includes device drivers, boot loaders, HALs, and other software components that are specific to the target hardware platform.
    46. What is a real-time operating system (RTOS) in Embedded C? A real-time operating system (RTOS) in Embedded C is a software system that is designed to provide deterministic and predictable behavior for real-time applications. An RTOS typically provides features such as task scheduling, inter-task communication, memory management, and interrupt handling, and can help to ensure reliable and efficient operation of the system.
    47. What is an event-driven programming model in Embedded C? An event-driven programming model in Embedded C is a programming paradigm where the application software is structured around the occurrence of specific events, such as user inputs, sensor readings, or timer events. The application software typically registers event handlers or callbacks that are executed in response to the occurrence of the associated event.
    48. What is a polling-based programming model in Embedded C? A polling-based programming model in Embedded C is a programming paradigm where the application software continuously checks for the occurrence of specific events, such as user inputs or sensor readings. The application software typically uses loops or timers to periodically poll for the occurrence of the associated events.
    49. What is a task in an RTOS in Embedded C? A task in an RTOS in Embedded C is a software component that represents a specific unit of work or activity that can be scheduled and executed by the operating system. Tasks typically have their own stack, context, and priority, and can communicate with other tasks through shared memory or message passing mechanisms.
    50. What is a semaphore in an RTOS in Embedded C? A semaphore in an RTOS in Embedded C is a synchronization mechanism that is used to coordinate access to shared resources or data between multiple tasks in an RTOS. A semaphore typically has a counter that is used to keep track of the number of available resources or the number of tasks waiting for the resource, and can be used to control the access to the shared resource.
    51. What is a mutex in an RTOS in Embedded C? A mutex (mutual exclusion) in an RTOS in Embedded C is a synchronization mechanism that is used to prevent concurrent access to a shared resource by multiple tasks. A mutex typically has a lock that can be acquired by one task at a time, and other tasks that try to acquire the lock while it is already held by another task are blocked until the lock is released.
    52. What is a message queue in an RTOS in Embedded C? A message queue in an RTOS in Embedded C is a data structure that is used to enable inter-task communication and data exchange. A message queue typically allows tasks to send and receive messages of a specific data type, and can be used to implement event notifications, data sharing, and synchronization between tasks.
    53. What is a timer in Embedded C? A timer in Embedded C is a hardware device that is used to generate periodic or one-shot events at specific intervals. The timer typically provides features such as period, duty cycle, and resolution, and can be used to implement time-based functions such as periodic interrupts, PWM output, and system scheduling.
    54. What is a watchdog timer in Embedded C? A watchdog timer in Embedded C is a hardware device that is used to detect and recover from software faults or system failures. The watchdog timer typically provides a timeout period, and the software is responsible for periodically resetting the timer to prevent it from triggering a system reset or other recovery mechanism.
    55. What is a interrupt in Embedded C? An interrupt in Embedded C is a mechanism that allows the hardware or software to temporarily halt the execution of the main program and transfer control to a specific interrupt service routine (ISR) in response to a specific event. Interrupts can be used to implement event-driven programming, real-time processing, and other time-critical tasks.
    56. What is an interrupt service routine (ISR) in Embedded C? An interrupt service routine (ISR) in Embedded C is a software function that is executed in response to a specific interrupt event. The ISR typically performs the necessary actions to handle the interrupt, such as reading or writing data, updating variables, or triggering other tasks or events.
    57. What is a vector table in Embedded C? A vector table in Embedded C is a data structure that is used to store the addresses of interrupt service routines (ISRs) for specific interrupt events. The vector table is typically located at a specific memory address and is initialized during system startup, and can be used to implement interrupt handling and other event-driven processing.
    58. What is a linker in Embedded C? A linker in Embedded C is a software tool that is used to combine and organize the compiled object files and libraries into a single executable image that can be loaded and run on the target system. The linker typically performs functions such as symbol resolution, memory allocation, and relocation, and can help to optimize the size and performance of the final executable image.
    59. What is a cross-compiler in Embedded C? A cross-compiler in Embedded C is a software tool that is used to compile and generate executable code for a target system that has a different architecture or operating system than the development system. The cross-compiler typically generates object files and libraries that are specific to the target system, and can help to ensure compatibility and optimal performance of the final executable image.
    60. What is a memory-mapped I/O in Embedded C? Memory-mapped I/O in Embedded C is a technique that allows the hardware devices or peripherals to be accessed through memory locations rather than through dedicated I/O ports. In memory-mapped I/O, each device or peripheral is assigned a unique address range in the memory map, and the software can read or write to the device by accessing the corresponding memory locations. This technique can simplify the software design and improve performance by allowing the devices to be accessed using standard load and store instructions.
    61. What is a memory-mapped register in Embedded C? A memory-mapped register in Embedded C is a special type of memory location that is used to control and configure the behavior of hardware devices or peripherals. The memory-mapped registers typically contain bit-fields that are used to configure various features or control the operation of the device, and can be read or written by the software to control the device behavior.
    62. What is a peripheral in Embedded C? A peripheral in Embedded C is a hardware device that is connected to the microcontroller or microprocessor and is used to provide additional functionality or interfaces to the system. Examples of peripherals include timers, serial ports, analog-to-digital converters, and LCD displays.
    63. What is an interrupt vector in Embedded C? An interrupt vector in Embedded C is a special memory location that contains the address of the interrupt service routine (ISR) for a specific interrupt event. When an interrupt occurs, the microcontroller or microprocessor reads the interrupt vector to determine the address of the ISR to execute, and transfers control to the ISR.
    64. What is DMA in Embedded C? DMA (direct memory access) in Embedded C is a hardware feature that allows data to be transferred between the memory and the peripheral devices without the involvement of the CPU. DMA can improve performance and reduce the overhead of data transfer by allowing the peripheral devices to access the memory directly.
    65. What is bit-banding in Embedded C? Bit-banding in Embedded C is a technique that allows individual bits in a memory location to be addressed and manipulated as separate variables. This technique can simplify the code and reduce the memory footprint by allowing the software to access individual bits directly, without the need for masking and shifting operations.
    66. What is a linker script in Embedded C? A linker script in Embedded C is a special file that is used by the linker to control the memory layout and organization of the executable image. The linker script typically contains information such as memory regions, segment sizes, and alignment, and can be used to optimize the memory usage and performance of the final executable.
    67. What is a target in Embedded C? A target in Embedded C is the hardware system or platform that the software is designed to run on. The target typically includes the microcontroller or microprocessor, the memory, the peripherals, and any other hardware components that are necessary for the system operation.
    68. What is an IDE in Embedded C? An IDE (integrated development environment) in Embedded C is a software tool that provides a comprehensive environment for software development, including editing, compiling, debugging, and project management. The IDE typically includes a text editor, a compiler, a linker, a debugger, and other tools and features that help to improve productivity and code quality.
    69. What is a flash memory in Embedded C? Flash memory in Embedded C is a type of non-volatile memory that can be programmed and erased electrically. Flash memory is commonly used in microcontrollers and microprocessors to store the firmware and other data that are required for system operation.
    70. What is an EEPROM in Embedded C? EEPROM (electrically erasable programmable read-only memory) in Embedded C is a type of non-volatile memory that can be electrically programmed and erased. EEPROM is commonly used in microcontrollers and microprocessors to store data that needs to be retained even when the power is turned off, such as configuration settings and calibration data.
    71. What is a bootloader in Embedded C? A bootloader in Embedded C is a program that is used to load the main firmware or application program into the microcontroller or microprocessor. The bootloader typically runs at startup and provides a way to transfer the firmware image from an external source, such as a serial port or a USB connection. Bootloaders can be used to update the firmware in the field without the need for specialized hardware or programming tools.
    72. What is the difference between volatile and non-volatile variables in Embedded C? Volatile variables in Embedded C are those that can change unexpectedly due to external factors, such as hardware interrupts or shared memory access. The volatile keyword is used to indicate that the variable should not be optimized or cached by the compiler, and that its value may change at any time. Non-volatile variables in Embedded C are those that retain their value even when the power is turned off, such as data stored in flash memory or EEPROM. These variables can be used to store configuration settings, calibration data, and other information that needs to be retained across power cycles.
    73. What is a watchdog timer in Embedded C? A watchdog timer in Embedded C is a hardware feature that is used to detect and recover from software errors or lockups. The watchdog timer is typically configured to generate a reset or an interrupt if it is not periodically reset by the software, indicating that the software is not functioning properly. The watchdog timer can be used to implement a self-recovering system that can detect and recover from faults without the need for human intervention.
    74. What is a real-time operating system (RTOS) in Embedded C? A real-time operating system (RTOS) in Embedded C is a specialized operating system that is designed to provide deterministic and predictable behavior for real-time applications. RTOSs typically provide features such as task scheduling, inter-task communication, synchronization, and memory management, and are commonly used in applications such as control systems, robotics, and embedded devices.
    75. What is a mutex in Embedded C? A mutex (short for mutual exclusion) in Embedded C is a synchronization object that is used to protect shared resources from simultaneous access by multiple tasks or threads. A mutex provides a mechanism for enforcing exclusive access to the shared resource, preventing race conditions and other synchronization errors.
    76. What is a semaphore in Embedded C? A semaphore in Embedded C is a synchronization object that is used to signal and coordinate access to shared resources between multiple tasks or threads. A semaphore provides a mechanism for controlling access to the shared resource, allowing only a certain number of tasks or threads to access it at a time.
    77. What is a task in an RTOS in Embedded C? A task in an RTOS (real-time operating system) in Embedded C is a unit of execution that represents a specific function or thread of execution. Tasks are typically scheduled by the RTOS and can communicate with each other using inter-task communication mechanisms such as message queues or semaphores.
    78. What is a context switch in Embedded C? A context switch in Embedded C is the process of saving and restoring the execution context of a task or thread when it is suspended and resumed. The context switch typically involves saving the processor state, such as the registers and the program counter, and switching to a new task or thread to execute.
    79. What is a priority inversion in Embedded C? A priority inversion in Embedded C is a situation where a higher-priority task is blocked by a lower-priority task that is currently holding a resource. This can lead to priority inversion and can cause real-time performance issues. Priority inversion can be mitigated using techniques such as priority inheritance or priority ceiling protocols.
  • Jupyter Notebook startup folder

    cd into the directory or a parent directory (with the intended directory you will work nested in it).Then just run the command jupyter notebook

    There are many ways you can change Jupiter notebook startup folder. Here I put a collection of them below for your reference.

    1. Change Jupyter Notebook startup folder (Windows)

    • Copy the Jupyter Notebook launcher from the menu to the desktop.
    • Right click on the new launcher and change the Target field, change %USERPROFILE% to the full path of the folder which will contain all the notebooks.
    • Double-click on the Jupyter Notebook desktop launcher (icon shows [IPy]) to start theJupyter Notebook App. The notebook interface will appear in a new browser window or tab. A secondary terminal window (used only for error logging and for shut down) will be also opened.

    2. Change Jupyter Notebook startup folder (Mac OS)

    To launch Jupyter Notebook App:

    • Click on spotlight, type terminal to open a terminal window.
    • Enter the startup folder by typing cd /some_folder_name.
    • Type jupyter notebook to launch the Jupyter Notebook App The notebook interface will appear in a new browser window or tab.

    3. From Jupyter notebook

    jupyter notebook --help-all could be of help:

    --notebook-dir=<Unicode> (NotebookManager.notebook_dir)
    Default: u'/Users/me/ipynbs'
    The directory to use for notebooks.

    For example:

    jupyter notebook --notebook-dir=/Users/yourname/folder1/folder2/

    You can of course set it in your profiles if needed, you might need to escape backslash in Windows.

    Note that this will override whatever path you might have set in a jupyter_notebook_config.py file. (Where you can set a variable c.NotebookApp.notebook_dir that will be your default startup location.)

    4. Configuration File

    Assuming you have several conda environments you can set up default directories for each as follows.

    1. Open a terminal for one of your environments (not the default one). You can do that from the Anaconda Navigator — Environments tab.
    2. If you don’t have a default configuration file, you need to create one by entering the command
    3. $ jupyter notebook --generate-config.
    4. This will create a default
    5. C:\Users\username\.jupyter\jupyter_notebook_config.py
    6. file (which will do nothing because everything is commented out in the file).
    7. Enter
    8. jupyter --paths.
    9. This lists the default paths for the environment you are working in. Look for the config path for your environment, e.g.
    10. config: ... C:\Users\username\Anaconda3\envs\envname\etc\jupyter
    11. You’ll probably find the directory doesn’t exist. Create it.
    12. Copy your jupyter_notebook_config.py file into the ...\etc\jupyter directory you just created.
    13. Edit the file — you are looking for the “c.NotebookApp.notebook_dir” entry. Enter the default directory path you want your notebook to open to. c.NotebookApp.notebook_dir = r"C:\Users\username\default_directory" (the ‘r’ string prefix saves you having to escape all the backslashes (the slashes go the other way in linux)). Uncomment the entry.

    5. os.chdir(NEW_PATH)

    Running os.chdir(NEW_PATH) will change the working directory.

    import os
    os.getcwd()
    Out[2]:
    '/tmp'
    In [3]:os.chdir('/')
    In [4]:
    os.getcwd()
    Out[4]:
    '/'
    In [ ]:

    A recent video of How to Change Jupyter Notebook Startup Folder or Directory.

  • Least Square Method

    The least squares method is a widely used method for approximating the solutions of systems of linear equations and for finding the best-fitting curve through a set of data points. The main advantages of the least squares method are:

    1. Simplicity: The least squares method is relatively simple to implement and understand, and it can be easily solved using matrix algebra.
    2. Robustness: The least squares method is relatively robust to errors in the data, and it can still produce good results even if the data contains outliers or noise.
    3. Versatility: The least squares method can be used to solve a wide range of problems, including linear and non-linear regression, curve fitting, and signal processing.
    4. Generalization: The least squares method can be used to find the best-fitting solution for any continuous and smooth function, this enables the generalization of the results obtained from the sample data.

    However, there are also some limitations of the least squares method:

    1. Linearity: The least squares method assumes that the relationship between the independent and dependent variables is linear. If the relationship is non-linear, the least squares method may not produce accurate results.
    2. Normality: The least squares method assumes that the errors in the data are normally distributed. If the errors are not normally distributed, the least squares method may not produce accurate results.
    3. Outliers: The least squares method is sensitive to outliers in the data, which can have a large impact on the results.
    4. Overfitting: The least squares method can be used to fit a model to a set of data points, but it can also be used to fit a model that is too complex for the data set, which can lead to overfitting.
    5. No uncertainty: The least squares method does not provide an estimate of the uncertainty of the solution, so it can be difficult to know how confident you can be in the results obtained.

    In summary, the least squares method is a powerful tool that can be used to find the best-fitting solutions for many types of problems, but it does have some limitations that should be taken into consideration when using it.

    Below code runs on an STM32 microcontroller and uses the C programming language. The script first defines the data points x and y and the variables A, AT, ATA, ATb, m, and c that will be used for the least squares solution.

    In the main() function, we first initialize the microcontroller, and then we initialize the matrices A, AT and ATA using nested loops. Then we calculate the least squares solution by multiplying the transpose of the matrix A with A and y. Finally, we calculate the slope m and y-intercept c from the solution and print the equation of the line in the form “y = mx + c” using the printf() function.

    #include "stm32f4xx.h"
    
    // Define the data points
    float x[5] = {1, 2, 3, 4, 5};
    float y[5] = {2, 4, 5, 4, 5};
    
    // Variables for the least squares solution
    float A[5][2], AT[2][5], ATA[2][2];
    float ATb[2], m, c;
    
    int main(void)
    {
        // Initialize the microcontroller
        // ...
    
        // Initialize the matrices
        for (int i = 0; i < 5; i++)
        {
            A[i][0] = x[i];
            A[i][1] = 1;
        }
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < 5; j++)
            {
                AT[i][j] = A[j][i];
            }
        }
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < 2; j++)
            {
                ATA[i][j] = 0;
                for (int k = 0; k < 5; k++)
                {
                    ATA[i][j] += AT[i][k] * A[k][j];
                }
            }
        }
    
        // Solve for the least squares solution
        for (int i = 0; i < 2; i++)
        {
            ATb[i] = 0;
            for (int j = 0; j < 5; j++)
            {
                ATb[i] += AT[i][j] * y[j];
            }
        }
        m = ATb[0] / ATA[0][0];
        c = ATb[1] / ATA[1][1];
    
        // Print the line equation
        printf("Line equation: y = %fx + %f\n", m, c);
    
        // ...
        while (1)
        {
            // Do other things
        }
    }
    
    
  • Ubuntu list of installed Apps

    List packages using apt command:

    apt list –installed

    apt list | grep nginx

    To list packages using dpkg command:

    dpkg-query -l

    To list Snap packages installed on your system:

    snap list

    To list Flatpak packages installed on your system:

    flatpak list

    Depending on the type of installation you need to go all of the above. So far there is no common list

  • Visual studio tab to space

    Visual studio tab to space

    To view tabs and spaces in visual studio use below shorcut

    CTRL+R + CTRL+W

    To convert tabs to white space use

    CTRL+K + CTRL+D

    To change the tab settings go to Tools->Options->Text Editor->All Languages->Tabs

    Then put 2 in indent size and 2 in tab size

  • PTC and NTC

    Thermistors: NTC and PTC Thermistors Explained – Latest Open Tech From Seeed (seeedstudio.com)

  • Create Ubuntu bootable USB

    Create Ubuntu bootable USB

    This section will cover download and making Ubuntu USB disk from Ubuntu OS.

    You will need:

    • A 4GB or larger USB stick/flash drive
    • Ubuntu Desktop 14.04 or later installed
    • An Ubuntu ISO file. See Get Ubuntu for download links

    After downloading the iso file, we’re going to use an application called ‘Startup Disk Creator’ to write the ISO image to your USB stick. This is installed by default on Ubuntu, and can be launched as follows:

    1. Insert your USB stick (select ‘Do nothing’ if prompted by Ubuntu)
    2. On Ubuntu 18.04 and later, use the bottom left icon to open ‘Show Applications’
    3. In older versions of Ubuntu, use the top left icon to open the dash
    4. Use the search field to look for Startup Disk Creator
    5. Select Startup Disk Creator from the results to launch the application

    ISO and USB selection

    When launched, Startup Disk Creator will look for the ISO files in your Downloads folder, as well as any attached USB storage it can write to.

    It’s likely that both your Ubuntu ISO and the correct USB device will have been detected and set as ‘Source disc image’ and ‘Disk to use’ in the application window. If not, use the ‘Other’ button to locate your ISO file and select the exact USB device you want to use from the list of devices.

    Click Make Startup Disk to start the process.

    After confirming, the write process will start and a progress bar appears. Then you will get a message for installation complete after few minutes. That’s it! You now have Ubuntu on a USB stick, bootable and ready to go.

  • Visual Studio Tips

    Multiline, multi variable and multi caret editing

    Visual Studio allows to edit multiple lines at the same time. This is very useful to apply the same change to multiple lines. For instance when you want to add the modifier to multiple properties.

    #Multi-line editing using the mouse

    Press Alt while selecting the block with the mouse:

    #Multi-line editing using the keyboard

    Press Alt+Shift+Arrow to select the block to edit:

    #Multi-carets editing

    If you want to edit multiple places that are unaligned, you can use the multi-cursor edit. Press Ctrl+Alt and click where you want to add a caret. The

    #Insert carets at all matching locations

    You can insert a caret at all places where the current word exists. Select the word you want to match and press Alt+Shift+;. Visual Studio will select all the locations that match the selected text in the current document.

    You can select just the next matching location by using Alt+Shift+.

    Reference:

    https://www.meziantou.net/visual-studio-tips-and-tricks-multi-line-and-multi-cursor-editing.htm

  • Google test

    Introduction: Why Google C++ Testing Framework?

    Google C++ Testing Framework helps you write better C++ tests.

    No matter whether you work on Linux, Windows, or a Mac, if you write C++ code, Google Test can help you.

    So what makes a good test, and how does Google C++ Testing Framework fit in? We believe:

    1. Tests should be independent and repeatable. It’s a pain to debug a test that succeeds or fails as a result of other tests. Google C++ Testing Framework isolates the tests by running each of them on a different object. When a test fails, Google C++ Testing Framework allows you to run it in isolation for quick debugging.
    2. Tests should be well organized and reflect the structure of the tested code. Google C++ Testing Framework groups related tests into test cases that can share data and subroutines. This common pattern is easy to recognize and makes tests easy to maintain. Such consistency is especially helpful when people switch projects and start to work on a new code base.
    3. Tests should be portable and reusable. The open-source community has a lot of code that is platform-neutral, its tests should also be platform-neutral. Google C++ Testing Framework works on different OSes, with different compilers (gcc, MSVC, and others), with or without exceptions, so Google C++ Testing Framework tests can easily work with a variety of configurations. (Note that the current release only contains build scripts for Linux – we are actively working on scripts for other platforms.)
    4. When tests fail, they should provide as much information about the problem as possible. Google C++ Testing Framework doesn’t stop at the first test failure. Instead, it only stops the current test and continues with the next. You can also set up tests that report non-fatal failures after which the current test continues. Thus, you can detect and fix multiple bugs in a single run-edit-compile cycle.
    5. The testing framework should liberate test writers from housekeeping chores and let them focus on the test content. Google C++ Testing Framework automatically keeps track of all tests defined, and doesn’t require the user to enumerate them in order to run them.
    6. Tests should be fast. With Google C++ Testing Framework, you can reuse shared resources across tests and pay for the set-up/tear-down only once, without making tests depend on each other.

    Since Google C++ Testing Framework is based on the popular xUnit architecture, you‘ll feel right at home if you’ve used JUnit or PyUnit before. If not, it will take you about 10 minutes to learn the basics and get started. So let’s go!

    Note: We sometimes refer to Google C++ Testing Framework informally as Google Test.

    Setting up a New Test Project

    To write a test program using Google Test, you need to compile Google Test into a library and link your test with it. We provide build files for some popular build systems: msvc/ for Visual Studio, xcode/ for Mac Xcode, make/ for GNU make, codegear/ for Borland C++ Builder, and the autotools script (deprecated) and CMakeLists.txt for CMake (recommended) in the Google Test root directory. If your build system is not on this list, you can take a look at make/Makefile to learn how Google Test should be compiled (basically you want to compile src/gtest-all.cc with GTEST_ROOT and GTEST_ROOT/include in the header search path, where GTEST_ROOT is the Google Test root directory).

    Once you are able to compile the Google Test library, you should create a project or build target for your test program. Make sure you have GTEST_ROOT/include in the header search path so that the compiler can find "gtest/gtest.h" when compiling your test. Set up your test project to link with the Google Test library (for example, in Visual Studio, this is done by adding a dependency on gtest.vcproj).

    If you still have questions, take a look at how Google Test’s own tests are built and use them as examples.

    Basic Concepts

    When using Google Test, you start by writing assertions, which are statements that check whether a condition is true. An assertion’s result can be success, nonfatal failure, or fatal failure. If a fatal failure occurs, it aborts the current function; otherwise the program continues normally.

    Tests use assertions to verify the tested code’s behavior. If a test crashes or has a failed assertion, then it fails; otherwise it succeeds.

    A test case contains one or many tests. You should group your tests into test cases that reflect the structure of the tested code. When multiple tests in a test case need to share common objects and subroutines, you can put them into a test fixture class.

    A test program can contain multiple test cases.

    We’ll now explain how to write a test program, starting at the individual assertion level and building up to tests and test cases.

    Assertions

    Google Test assertions are macros that resemble function calls. You test a class or function by making assertions about its behavior. When an assertion fails, Google Test prints the assertion‘s source file and line number location, along with a failure message. You may also supply a custom failure message which will be appended to Google Test’s message.

    The assertions come in pairs that test the same thing but have different effects on the current function. ASSERT_* versions generate fatal failures when they fail, and abort the current function. EXPECT_* versions generate nonfatal failures, which don‘t abort the current function. Usually EXPECT_* are preferred, as they allow more than one failures to be reported in a test. However, you should use ASSERT_* if it doesn’t make sense to continue when the assertion in question fails.

    Since a failed ASSERT_* returns from the current function immediately, possibly skipping clean-up code that comes after it, it may cause a space leak. Depending on the nature of the leak, it may or may not be worth fixing – so keep this in mind if you get a heap checker error in addition to assertion errors.

    To provide a custom failure message, simply stream it into the macro using the << operator, or a sequence of such operators. An example:

    ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
    
    for (int i = 0; i < x.size(); ++i) {
      EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
    }
    

    Anything that can be streamed to an ostream can be streamed to an assertion macro–in particular, C strings and string objects. If a wide string (wchar_t*, TCHAR* in UNICODE mode on Windows, or std::wstring) is streamed to an assertion, it will be translated to UTF-8 when printed.

    Basic Assertions

    These assertions do basic true/false condition testing.

    Fatal assertionNonfatal assertionVerifies
    ASSERT_TRUE(condition);EXPECT_TRUE(condition);condition is true
    ASSERT_FALSE(condition);EXPECT_FALSE(condition);condition is false

    Remember, when they fail, ASSERT_* yields a fatal failure and returns from the current function, while EXPECT_* yields a nonfatal failure, allowing the function to continue running. In either case, an assertion failure means its containing test fails.

    Availability: Linux, Windows, Mac.

    Binary Comparison

    This section describes assertions that compare two values.

    Fatal assertionNonfatal assertionVerifies
    ASSERT_EQ(val1, val2);EXPECT_EQ(val1, val2);val1 == val2
    ASSERT_NE(val1, val2);EXPECT_NE(val1, val2);val1 != val2
    ASSERT_LT(val1, val2);EXPECT_LT(val1, val2);val1 < val2
    ASSERT_LE(val1, val2);EXPECT_LE(val1, val2);val1 <= val2
    ASSERT_GT(val1, val2);EXPECT_GT(val1, val2);val1 > val2
    ASSERT_GE(val1, val2);EXPECT_GE(val1, val2);val1 >= val2

    In the event of a failure, Google Test prints both val1 and val2.

    Value arguments must be comparable by the assertion‘s comparison operator or you’ll get a compiler error. We used to require the arguments to support the << operator for streaming to an ostream, but it’s no longer necessary since v1.6.0 (if << is supported, it will be called to print the arguments when the assertion fails; otherwise Google Test will attempt to print them in the best way it can. For more details and how to customize the printing of the arguments, see this Google Mock recipe.).

    These assertions can work with a user-defined type, but only if you define the corresponding comparison operator (e.g. ==, <, etc). If the corresponding operator is defined, prefer using the ASSERT_*() macros because they will print out not only the result of the comparison, but the two operands as well.

    Arguments are always evaluated exactly once. Therefore, it‘s OK for the arguments to have side effects. However, as with any ordinary C/C++ function, the arguments’ evaluation order is undefined (i.e. the compiler is free to choose any order) and your code should not depend on any particular argument evaluation order.

    ASSERT_EQ() does pointer equality on pointers. If used on two C strings, it tests if they are in the same memory location, not if they have the same value. Therefore, if you want to compare C strings (e.g. const char*) by value, use ASSERT_STREQ() , which will be described later on. In particular, to assert that a C string is NULL, use ASSERT_STREQ(NULL, c_string) . However, to compare two string objects, you should use ASSERT_EQ.

    Macros in this section work with both narrow and wide string objects (string and wstring).

    Availability: Linux, Windows, Mac.

    Historical note: Before February 2016 *_EQ had a convention of calling it as ASSERT_EQ(expected, actual), so lots of existing code uses this order. Now *_EQ treats both parameters in the same way.

    String Comparison

    The assertions in this group compare two C strings. If you want to compare two string objects, use EXPECT_EQ, EXPECT_NE, and etc instead.

    Fatal assertionNonfatal assertionVerifies
    ASSERT_STREQ(str1, str2);EXPECT_STREQ(str1, _str_2);the two C strings have the same content
    ASSERT_STRNE(str1, str2);EXPECT_STRNE(str1, str2);the two C strings have different content
    ASSERT_STRCASEEQ(str1, str2);EXPECT_STRCASEEQ(str1, str2);the two C strings have the same content, ignoring case
    ASSERT_STRCASENE(str1, str2);EXPECT_STRCASENE(str1, str2);the two C strings have different content, ignoring case

    Note that “CASE” in an assertion name means that case is ignored.

    *STREQ* and *STRNE* also accept wide C strings (wchar_t*). If a comparison of two wide strings fails, their values will be printed as UTF-8 narrow strings.

    A NULL pointer and an empty string are considered different.

    Availability: Linux, Windows, Mac.

    See also: For more string comparison tricks (substring, prefix, suffix, and regular expression matching, for example), see the Advanced Google Test Guide.

    Simple Tests

    To create a test:

    1. Use the TEST() macro to define and name a test function, These are ordinary C++ functions that don’t return a value.
    2. In this function, along with any valid C++ statements you want to include, use the various Google Test assertions to check values.
    3. The test’s result is determined by the assertions; if any assertion in the test fails (either fatally or non-fatally), or if the test crashes, the entire test fails. Otherwise, it succeeds.
    TEST(test_case_name, test_name) {
     ... test body ...
    }
    

    TEST() arguments go from general to specific. The first argument is the name of the test case, and the second argument is the test‘s name within the test case. Both names must be valid C++ identifiers, and they should not contain underscore (_). A test’s full name consists of its containing test case and its individual name. Tests from different test cases can have the same individual name.

    For example, let’s take a simple integer function:

    int Factorial(int n); // Returns the factorial of n
    

    A test case for this function might look like:

    // Tests factorial of 0.
    TEST(FactorialTest, HandlesZeroInput){  
     EXPECT_EQ(1, Factorial(0));
    }
    // Tests factorial of positive numbers.
    TEST(FactorialTest, HandlesPositiveInput){
      EXPECT_EQ(1, Factorial(1));
      EXPECT_EQ(2, Factorial(2));
      EXPECT_EQ(6, Factorial(3));
      EXPECT_EQ(40320, Factorial(8));
    }
    

    Google Test groups the test results by test cases, so logically-related tests should be in the same test case; in other words, the first argument to their TEST() should be the same. In the above example, we have two tests, HandlesZeroInput and HandlesPositiveInput, that belong to the same test case FactorialTest.

    Availability: Linux, Windows, Mac.

    Test Fixtures: Using the Same Data Configuration for Multiple Tests

    If you find yourself writing two or more tests that operate on similar data, you can use a test fixture. It allows you to reuse the same configuration of objects for several different tests.

    To create a fixture, just:

    1. Derive a class from ::testing::Test . Start its body with protected: or public: as we’ll want to access fixture members from sub-classes.
    2. Inside the class, declare any objects you plan to use.
    3. If necessary, write a default constructor or SetUp() function to prepare the objects for each test. A common mistake is to spell SetUp() as Setup() with a small u – don’t let that happen to you.
    4. If necessary, write a destructor or TearDown() function to release any resources you allocated in SetUp() . To learn when you should use the constructor/destructor and when you should use SetUp()/TearDown(), read this FAQ entry.
    5. If needed, define subroutines for your tests to share.

    When using a fixture, use TEST_F() instead of TEST() as it allows you to access objects and subroutines in the test fixture:

    TEST_F(test_case_name, test_name) {
     ... test body ...
    }
    

    Like TEST(), the first argument is the test case name, but for TEST_F() this must be the name of the test fixture class. You’ve probably guessed: _F is for fixture.

    Unfortunately, the C++ macro system does not allow us to create a single macro that can handle both types of tests. Using the wrong macro causes a compiler error.

    Also, you must first define a test fixture class before using it in a TEST_F(), or you’ll get the compiler error “virtual outside class declaration”.

    For each test defined with TEST_F(), Google Test will:

    1. Create a fresh test fixture at runtime
    2. Immediately initialize it via SetUp() ,
    3. Run the test
    4. Clean up by calling TearDown()
    5. Delete the test fixture. Note that different tests in the same test case have different test fixture objects, and Google Test always deletes a test fixture before it creates the next one. Google Test does not reuse the same test fixture for multiple tests. Any changes one test makes to the fixture do not affect other tests.

    As an example, let’s write tests for a FIFO queue class named Queue, which has the following interface:

    template <typename E> // E is the element type.
    class Queue {
     public:
      Queue();
      void Enqueue(const E& element);
      E* Dequeue(); // Returns NULL if the queue is empty.
      size_t size() const;
      ...
    };
    

    First, define a fixture class. By convention, you should give it the name FooTest where Foo is the class being tested.

    class QueueTest : public ::testing::Test {
     protected:
      virtual void SetUp() {
        q1_.Enqueue(1);
        q2_.Enqueue(2);
        q2_.Enqueue(3);
      }
    
      // virtual void TearDown() {}
    
      Queue<int> q0_;
      Queue<int> q1_;
      Queue<int> q2_;
    };
    

    In this case, TearDown() is not needed since we don‘t have to clean up after each test, other than what’s already done by the destructor.

    Now we’ll write tests using TEST_F() and this fixture.

Design a site like this with WordPress.com
Get started