Dumping STM32F105 Firmware on Ubuntu using ST-LINKMB_CAN_Filter Board
I recently got a CAN bus filter from AliExpress MB_CAN_FIlter. The existing firmware is used to bypass the Odometer of the premium cars like Mercedes, BMW by modifying the CAN signal that are passed through it. But we can utilize this for better endeavors like resetting the BMS signals of EVs to expand the lifetime of the battery and replacing batteries of higher capacity.
So it is essential to understand how this Circuit works, and learn the Basics of dumping the existing firmware and flashing new firmware to the Chip it is using.
The board here uses a STM32F105C8T6 Microcontroller and the CAN Transceivers ICs are some TJA1057. There is a similar board that uses the MCP2551.
There are multiple reasons why this board is wonderful as well as has many issues related to the PCB in which I will be going through maybe will opensource the designs in the future.
Dumping STM32F105 Firmware on Ubuntu using ST-LINK
This guide details how to install the required tools and dump the firmware from an STM32F105 microcontroller using an ST-LINK programmer on an Ubuntu system. We will cover two common tools: STM32CubeProgrammer (the official ST tool) and OpenOCD (an open-source alternative).
1. Prerequisites
Hardware:
STM32F105-based board (See Section 3 for a specific example).
ST-LINK V2 or V3 programmer/debugger.
USB cables for the ST-LINK and potentially the target board (if it needs separate power).
Jumper wires for SWD connection.
Software:
Ubuntu Linux (instructions tested on recent LTS versions like 20.04/22.04).
Internet connection for downloads.
2. Tool Installation
a) STM32CubeProgrammer
STM32CubeProgrammer is STMicroelectronics' official tool for programming STM32 devices. It replaces older tools like ST-LINK Utility and STM Flasher.
Install Java: CubeProgrammer requires Java. Check if it's installed and install it if necessary:
java -version
# If not installed or version is too old:
sudo apt update
sudo apt install default-jre -y
Extract: Unzip the downloaded file:
unzip en.stm32cubeprg-lin_*.zip -d stm32cubeprogrammer
cd stm32cubeprogrammer
Run Installer: Execute the Linux installer script. You might need to make it executable first.
chmod +x SetupSTM32CubeProgrammer*.linux
sudo ./SetupSTM32CubeProgrammer*.linux
# Or run without sudo for user-local installation if preferred
# ./SetupSTM32CubeProgrammer*.linux
Follow the on-screen installation steps. The default installation location is often /usr/local/STMicroelectronics/STM32Cube/STM32CubeProgrammer/.
Add to PATH (Optional): To run the command-line interface (CLI) easily, add its directory to your PATH. Find the bin directory within your installation path (e.g., /usr/local/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin) and add it to your ~/.bashrc or ~/.zshrc:
sudo udevadm control --reload-rules
sudo udevadm trigger
Reconnect: Unplug and replug your ST-LINK programmer.
3. Hardware Overview (User's Board Example)
This section describes the specific hardware components mentioned for the target board being used in this example.
Microcontroller:STM32F105C8T6
Rationale: This MCU from the STM32F1 series (Connectivity Line) is chosen primarily for its dual CAN interfaces (bxCAN), which is essential for applications requiring communication on two separate CAN buses (e.g., bridging, gateway). Additionally, many of its GPIO pins are 5V tolerant, which simplifies interfacing with 5V peripherals like some CAN transceivers, although direct connection still requires careful consideration of signal levels.
CAN Transceiver:TJA1057
Rationale: This is a high-speed CAN transceiver. Compared to other common options in the TJA10xx family (like the TJA1050), the TJA1057 often provides improved ElectroMagnetic Compatibility (EMC) and ElectroStatic Discharge (ESD) performance. It might also offer features like specific low-power modes or better behavior under bus fault conditions, making it a robust choice for CAN communication.
Voltage Regulators:AMS1117-3.3 (3.3V LDO) and AMS1117-5.0 (5V LDO)
Function: These are Linear Low-Dropout regulators used to provide stable 3.3V (for the MCU and potentially other logic) and 5V (likely for the CAN transceiver VCC or other peripherals) from a higher input voltage.
Potential Board Design Considerations/Issues:
LDO Inefficiency: Using AMS1117 LDOs, especially for significant voltage drops (e.g., 12V input down to 5V or 3.3V) or higher current demands, leads to power loss as heat. This can reduce overall efficiency and potentially require heatsinking. Switch-mode buck converters are generally more efficient but add complexity and potential noise. LDOs like the AMS1117 also require specific types and values of input/output capacitors for stability, which must be correctly implemented.
Non-Automotive Grade MCU: The STM32F105C8T6 is typically a commercial or industrial grade component. If the application is intended for automotive environments, using a non-automotive qualified MCU might pose risks regarding temperature range limitations, long-term reliability, and lack of specific automotive certifications (AEC-Q100).
Lack of Feedback LEDs: The absence of status LEDs (e.g., Power OK, CAN TX/RX activity, Heartbeat) makes visual debugging and diagnostics difficult. It's hard to tell if the board is powered correctly or if communication is active without external measurement tools.
Noise Reduction and EMI Protection: For reliable CAN communication, especially at high speeds or in noisy environments, careful PCB layout, proper CAN bus termination (e.g., 120-ohm resistors), common-mode chokes, and potentially transient voltage suppression (TVS) diodes are crucial. Lacking these can lead to communication errors or susceptibility to electromagnetic interference.
4. Connecting Hardware (ST-LINK SWD)
Connect the ST-LINK programmer to your STM32F105 board using the SWD interface:
ST-LINK SWDIO <--> Target SWDIO (often PA13)
ST-LINK SWCLK <--> Target SWCLK (often PA14)
ST-LINK GND <--> Target GND
ST-LINK VCC/VDD <--> Target VDD (usually 3.3V, ensure voltage matches the MCU's VDD)
(Optional but Recommended) ST-LINK NRST <--> Target NRST (Reset pin)
Ensure the target board is powered on (using its own power supply, likely regulated by the onboard AMS1117s).
5. Dumping Firmware
The STM32F105 typically has Flash memory starting at address 0x08000000. The size varies; the C8 variant usually has 64KB (0x10000 bytes), but the F105 line goes up to 256KB (0x40000 bytes). Verify the exact flash size for your STM32F105C8T6 (it's 64KB) and adjust the size parameter accordingly.
This command attempts to connect via SWD at 4MHz and read a device ID register. It should output some information about the connected device if successful.
Read Flash to Binary File (for STM32F105C8T6 - 64KB):
# Use 0x10000 for 64KB Flash size
STM32_Programmer_CLI -c port=SWD freq=4000 mode=NORMAL -r 0x08000000 0x10000 firmware_dump.bin
This reads 64KB (0x10000 bytes) starting from address 0x08000000 and saves it to firmware_dump.bin.
Read Flash to Hex File (for STM32F105C8T6 - 64KB):
This saves the firmware in Intel HEX format instead of raw binary.
b) Using OpenOCD
Start OpenOCD: Open a terminal and run:
# Use stlink-v2.cfg for ST-LINK V2, stlink.cfg often works for V2/V3
# stm32f1x.cfg is the target configuration for the STM32F1 series
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg
OpenOCD connection output example
OpenOCD will try to connect to the target. Look for output indicating successful connection and halting the target CPU. It should also detect the flash size (likely reporting 64k).
Connect via Telnet: Open another terminal window and connect to the OpenOCD server (which listens on port 4444 by default):
telnet localhost 4444
Telnet connection output
Halt CPU (if not already halted):
> halt
Dump Firmware (for STM32F105C8T6 - 64KB): Use the dump_image command:
# dump_image <filename> <address> <size>
# Use 0x10000 for 64KB flash size
> dump_image firmware_dump_openocd.bin 0x08000000 0x10000
This command reads 64KB from flash address 0x08000000 and saves it to firmware_dump_openocd.bin in the directory where you launched OpenOCD.
Exit Telnet: Type exit and press Enter.
Shutdown OpenOCD: Go back to the first terminal (where OpenOCD is running) and press Ctrl+C to stop it.
6. Troubleshooting
Permission Denied / Cannot Open Device: Ensure udev rules are correctly set up and applied, or run the command using sudo (not recommended for regular use).
Cannot Connect / Target Not Found:
Double-check SWD wiring (SWDIO, SWCLK, GND, VDD).
Ensure the target board is powered correctly via its regulators.
Try lowering the SWD frequency (freq=1000 in CubeProgrammer, adapter speed 1000 in OpenOCD telnet session).
Try connecting under reset: Use mode=UR (Under Reset) in CubeProgrammer, or add connect_assert_srst to the OpenOCD command line before -f target/.... Ensure the NRST line is connected.
Check if the debug pins (SWDIO/SWCLK) have been disabled by the firmware. If so, connecting under reset might be the only option.
OpenOCD Errors: Pay attention to the specific error messages. Sometimes the wrong interface or target script is used. Ensure the detected flash size matches your expectation (64k for C8T6).
You now have the firmware dumped as a .bin or .hex file, which you can analyze or use as a backup.
From each step it is possible to Dump the Firmware.
Using OpenOCD we can also reset the fuses that are used in the MCU, if you look at the code, I reset the fuses that had set the STM32 to read only mode. Doing so can reduce the effects of corruption of the firmware.
Have you ever wondered if you could take any device and control it from your phone? Well, I did! I wanted to transform my home roller gate into a WiFi-controlled system, eliminating the unreliable RF remote provided by the manufacturer.
The Problem with Manufacturer-Provided Remotes
The RF remote that came with my roller gate has been a constant source of frustration:
Excessive Battery Drain: The remote’s battery runs out too quickly.
Lost Programming: The remote frequently forgets its paired state.
Manufacturer Dependency: If the remote malfunctions, I have to rely on the manufacturer to fix it.
To make things worse, the battery used in these remotes is:
Difficult to find in Sri Lanka
Toxic and disposable – A single-use battery with harmful compounds
Additionally, for some unknown reason, the system often loses its remote pairing, requiring reprogramming. While the controller board has a "Learn Mode", the manufacturer insists on doing the reprogramming themselves, which is both inconvenient and unnecessary.
And let’s not forget the cost—if you lose or damage a remote, replacing it costs over 3,000 rupees!
Time to Put My Electronics Degree to Work!
With all these issues piling up, I decided to take matters into my own hands. Using my background in electronics, I set out to build a WiFi-based solution that would allow me to control my roller gate from anywhere—no more unreliable remotes!
Reverse Engineering the Gate Controller
Curious about how the gate controller worked, I decided to take apart the control board and see if I could integrate my own system. On the right side of the board, I found a green terminal block with markings for different functions:
UP
DOWN
STOP
Each pin was pulled up to 12V, meaning that shorting them to ground would activate the corresponding function. This was great news! It meant I could control the gate using simple transistors.
Designing the Circuit
To interface with the controller, I designed a simple circuit that allows an ESP32-C3 to switch these functions using three 2N3904 NPN transistors. Here's the schematic:
When the ESP32 outputs HIGH (3.3V), the transistor turns on, connecting the collector (C) to ground and activating the corresponding gate function (by pulling the 12V pin low).
The emitter (E) is tied to ground to complete the circuit.
Prototyping the System
With the circuit planned out, I quickly soldered a prototype using:
This setup allowed me to control the gate wirelessly—no more dependency on the unreliable RF remote!
Setting Up the ESP32-C3 Supermini Web Server
To make the gate easily controllable from anywhere in my home, I configured the ESP32-C3 Supermini to:
Connect to my local WiFi network
Create its own Access Point (AP) for direct access
Host a web server that serves a control interface
Use mDNS so I can access it via a simple URL (e.g., `gatecontroller.local`)
With this setup, I could control my gate wirelessly from my phone or computer—no more unreliable RF remotes!
Debugging a Strange ESP32-C3 Issue
During unit testing, everything worked perfectly. But once I soldered the ESP32 to the circuit and tried running the system, I was shocked—it wouldn't connect to WiFi!
I started troubleshooting:
Was it a soldering issue? 🤔 I checked all joints—everything seemed fine.
Was the antenna faulty? I applied pressure on the chip antenna, and suddenly, it connected! 🤨
Re-soldering the antenna? Still no luck.
Replacing the antenna? Same issue.
At this point, I needed an expert opinion. I reached out to Dilshan Jayakody, my mentor, who suggested:
💡 The issue might be WiFi power instability—the 5V rail capacitor could be too small to handle sudden power spikes when both WiFi AP and STA mode were running simultaneously.
The Fix: Adding a 470µF Capacitor
I soldered a 470µF capacitor across the 5V power input pins of the ESP32 module to stabilize the voltage… and it worked like a charm! 🎉
With the WiFi issue solved, I completed the prototype, connected everything, and finally tested the gate control. Success!
The Next Problem: Manual Buttons Stopped Working
Just when I thought everything was perfect, I realized that the manual control buttons on the gate weren’t working when my device was connected. It turned out my circuit was interfering with the existing buttons.
Instead of using three separate transistors for UP, DOWN, and STOP, I looked closer at the controller board and found a 1-key operation input (often labeled 'OSC' or similar) that cycles through the states:
🔼 UP → ⏹️ STOP → 🔽 DOWN → ⏹️ STOP → (repeat)
This meant I only needed one transistor connected to this single input pin to operate the gate instead of three! I modified the circuit to use just one GPIO and one transistor connected to the 1-key input. A simple modification, and now everything worked perfectly, including the original manual buttons. ✅
Future Improvements
🚀
Design a dedicated PCB for a cleaner, more compact, and reliable build.
⚡
Replace the LM7805 linear regulator with an efficient SMPS buck converter (like MP1584EN or similar) to reduce heat generation and power consumption.
📦
Build a weatherproof enclosure using a standard project box with cable glands to protect the circuit from the elements.
This has been an exciting journey of reverse engineering, prototyping, and debugging! I want to thank Dilshan Jayakody again for his invaluable guidance. Innovation often starts with tackling everyday frustrations—so keep experimenting, learning, and stay curious!
Note: Everything Written Here is from LLMs (OpenAI and Deepseek)
Introduction to DeepSeek
DeepSeek is a powerful AI tool designed for natural language processing and deep learning tasks, often relying on GPUs to accelerate computation. However, not everyone has access to high-performance GPUs, and DeepSeek's adaptability allows it to be deployed on CPU-only systems. In this blog post, I'll demonstrate how to run DeepSeek on a self-hosted server, specifically an 11th Gen Intel i5 laptop CPU. We'll leverage Ollama for model optimization and Docker for containerized deployment, ensuring an efficient and streamlined setup. Whether you're exploring AI for personal projects or lightweight applications, this guide will help you make the most of your hardware resources.
Installing Docker on Linux, macOS, and Windows
Docker is a powerful tool for containerization, making it easy to run and deploy applications in isolated environments. Here's how to install Docker on the three major operating systems.
1. Installing Docker on Linux
For Ubuntu, Debian, and similar distributions:
Step 1: Update your system
sudo apt update
sudo apt upgrade -y
Step 2: Install required dependencies
sudo apt install -y ca-certificates curl gnupg
Step 3: Add Docker’s official GPG key and repository
During the installation, ensure the option Enable WSL 2 features is selected (required for Windows 10/11).
Step 3: Start Docker
Launch Docker Desktop from the Start Menu.
Sign in with your Docker Hub account or create one.
Step 4: Verify installation
Open PowerShell or Command Prompt and run:
docker --version
Post-Installation Tips
Add Your User to the Docker Group (Linux):
sudo usermod -aG docker $USER
Log out and back in to apply changes.
Test Docker Installation:
Run a test container:
docker run hello-world
Install Docker Compose (if not included):
docker compose version
Install a Frontend for the LLM
After setting up Docker and Ollama, install a frontend like Chatbox.ai or open-webui for a user-friendly chat interface.
Open-WEBUI Interface
Installing Ollama
Ollama is a tool for running large language models (LLMs) locally. It simplifies model management and allows running advanced AI models on your hardware.
1. Installing Ollama on macOS
Ollama currently supports macOS natively. Here's how to install it:
Install Ollama via Homebrew:
brew install ollama/tap/ollama
Start the Ollama service:
ollama serve
Verify Installation:
Run the following command to confirm:
ollama --version
2. Installing Ollama on Windows or Linux
Ollama doesn't yet natively support Windows or Linux, but you can run it on these platforms via macOS virtualization or containerization solutions like Docker. Stay updated by visiting the Ollama official site.
Downloading and Running Different DeepSeek LLMs
Once Ollama is installed, you can easily install and run models like DeepSeek.
1. Install a Model
To install a model, use the ollama run command. This will pull the model if it's not already downloaded. For example, to install and run a DeepSeek model:
ollama run deepseek-r1:8b
(Replace 8b with the desired model size)
2. List Available Models
To see all installed models:
ollama list
3. Run a Model
To use a specific installed model:
ollama run <model_name>
Example:
ollama run deepseek-r1:8b
4. Managing Models
Delete a Model: If you need to remove a model to free up space:
ollama rm <model_name>
Example:
ollama rm deepseek-r1:8b
5. Testing and Using DeepSeek LLMs
You can interact with the DeepSeek models through the terminal after running them. For example:
ollama run deepseek-r1:8b
Then, type your input query to test the model's capabilities.
DeepSeek Models Available
DeepSeek provides multiple models optimized for various tasks. Common versions include:
# 1.5B version (smallest):
ollama run deepseek-r1:1.5b
# 8B version:
ollama run deepseek-r1:8b
# 14B version:
ollama run deepseek-r1:14b
# 32B version:
ollama run deepseek-r1:32b
# 70B version (biggest/smartest):
ollama run deepseek-r1:70b
This is the command to run and install a model from Ollama:
ollama run deepseek-r1:8b
Screenshots
Conclusion
In conclusion, running DeepSeek on an 11th Gen Intel i5 laptop CPU proves to be a practical solution for lightweight AI workloads. With the 8B model, the system achieves a processing speed of 1.5–2 words per second, making it perfectly suitable for small-scale applications. While it utilizes around 80–90% of the CPU during operation, the performance is stable and reliable, demonstrating that even modest hardware can power advanced language models effectively when optimized with tools like Ollama and Docker.
Ansible is an open-source automation tool used for configuration management, application deployment, and task automation. It simplifies complex IT tasks by automating repetitive processes, making it easier to manage large-scale systems.
Key Features of Ansible
Agentless: Unlike other automation tools, Ansible does not require any agent software to be installed on the managed nodes. It uses SSH for communication, making it lightweight and easy to set up.
Declarative Language: Ansible uses a simple, human-readable language called YAML (Yet Another Markup Language) to define automation tasks. This makes it accessible to both developers and system administrators.
Idempotency: Ansible ensures that tasks are idempotent, meaning they can be run multiple times without changing the system's state if it is already in the desired state.
Extensible: Ansible has a modular architecture, allowing users to extend its functionality with custom modules, plugins, and roles.
Use Cases
Configuration Management: Ansible can manage the configuration of servers, ensuring they are set up consistently and correctly.
Application Deployment: Automate the deployment of applications across multiple servers, reducing the risk of human error.
Orchestration: Coordinate complex workflows and processes across different systems and environments.
Provisioning: Set up and configure new servers and infrastructure components.
Getting Started with Ansible
Install Ansible: You can install Ansible using package managers like pip, apt, or yum. For example, to install Ansible using pip, run:
bash
pip install ansible
Create an Inventory File: An inventory file lists the hosts and groups of hosts that Ansible will manage. Here's an example of a simple inventory file:
Run the Playbook: Use the ansible-playbook command to run the playbook:
bash
ansible-playbook -i inventory playbook.yml
Benefits of Using Ansible
Simplicity: Ansible's straightforward syntax and agentless architecture make it easy to learn and use.
Scalability: Ansible can manage thousands of nodes efficiently, making it suitable for large-scale environments.
Flexibility: Ansible can be used for a wide range of automation tasks, from simple configuration management to complex orchestration
Why Use Ansible Rather than Jenkins
Configuration Management: Ansible excels in configuration management, automation, and orchestration, while Jenkins is primarily a CI/CD tool.
Agentless Architecture: Ansible operates without the need for agents on target machines, simplifying setup and reducing overhead.
Ease of Use: Ansible uses a simple, human-readable YAML syntax, making it easier to write and understand automation scripts.
Idempotency: Ansible ensures tasks are idempotent, maintaining consistency in your infrastructure.
Integration: Ansible integrates well with a wide range of tools and platforms, focusing on infrastructure management and automation.
Declarative Approach: Ansible follows a declarative approach, defining the desired state, while Jenkins follows an imperative approach, defining the steps to be executed
As I use Jenkins for Work, it was a refreshing to learn Ansible for Deployments.
This code creates a basic HTTP server that listens on port 3000 and responds with "Hello, World!" when accessed
Using Deno for a NodeJS replacement,
Deno is a modern runtime for JavaScript and TypeScript, created by Ryan Dahl, the original developer of It was designed to address some of the shortcomings of and to provide a more secure and efficient environment for running JavaScript and TypeScript code. Here are some advantages of Deno over Node.js:
Security: Deno has a secure-by-default approach. It runs code in a sandboxed environment and requires explicit permissions for file system access, network access, and environment variables. This reduces the risk of security vulnerabilities.
TypeScript Support: Deno has built-in support for TypeScript, allowing you to write and run TypeScript code without the need for additional tools or configuration. This makes it easier to work with TypeScript out of the box.
Simplified Dependency Management: Deno uses URL-based imports for dependencies, eliminating the need for a separate package manager like npm. This simplifies dependency management and reduces the risk of dependency-related issues.
Standard Library: Deno comes with a standard library that is audited and maintained by the Deno team. This ensures a consistent and reliable set of APIs for common tasks, reducing the need for third-party libraries.
Modern Features: Deno leverages modern JavaScript features and web standards, making it more aligned with current web development practices. It also includes built-in development tooling, such as a linter, formatter, and test runner.
Single Executable: Deno is distributed as a single executable file, making it easy to install and use without the need for additional setup or configuration.
While Deno offers several advantages, it's important to consider your specific use case and requirements when choosing between Deno and has a mature ecosystem, extensive community support, and a vast library of packages, which can be beneficial for many projects.
Setting Up PIP for Python 3+ on Ubuntu 24 and Above Using pip.conf
Setting Up PIP for Python 3+ on Ubuntu 24 and Above Using pip.conf
Introduction
This guide will walk you through the steps to get PIP install commands working for Python 3+ on Ubuntu 24 and above, using the pip.conf configuration file.
In this the Pip Configuration is created because newer versions dont allow PIP packages to be installed from anysite, but the APT repo accepted libraries only
Step 1: Install Python 3 and PIP
Update System Packages:
sudo apt update
sudo apt upgrade
Install Python 3 (if not already installed):
sudo apt install python3
Install PIP for Python 3:
sudo apt install python3-pip
Verify PIP Installation:
pip3 --version
Step 2: Configure pip.conf
Create or Edit pip.conf:
Create the pip.conf file in the appropriate directory. For user-specific configuration, create it in ~/.config/pip/. For global configuration, create it in /etc/pip/.
Add Configuration Settings:
Open the pip.conf file in a text editor and add the following settings:
[global]
break-system-packages = true
Step 3: Using PIP with the Configuration
Install a Python Package:
pip3 install <package-name>
Upgrade a Python Package:
pip3 install --upgrade <package-name>
Uninstall a Python Package:
pip3 uninstall <package-name>
Conclusion
By following these steps, you can ensure that PIP install commands work seamlessly for Python 3+ on Ubuntu 24 and above, using the pip.conf configuration file. This setup will help you manage Python packages efficiently and avoid common issues related to package installations.
Feel free to reach out if you need any further assistance! 🚀