Platform Differences¶
The EmbSec Kit supports multiple target platforms, each with unique characteristics. Understanding these differences is crucial for developing portable labs and ensuring consistent behavior across environments.
Supported Platforms¶
1. TM4C123GH6PM (Hardware)¶
- Architecture: ARM Cortex-M4F
- Flash: 256 KB
- RAM: 32 KB
- Clock: Up to 80 MHz
- FPU: Hardware floating-point
- Use Case: Physical hardware labs
2. LM3S6965 (QEMU)¶
- Architecture: ARM Cortex-M3
- Flash: 256 KB
- RAM: 64 KB
- Clock: Simulated
- FPU: None (software emulation)
- Use Case: Development and testing
3. Host Platform (Testing)¶
- Architecture: x86_64 or ARM64
- Memory: Host system memory
- Use Case: Unit testing and development
Key Differences¶
Memory Layout¶
TM4C123GH6PM¶
0x00000000 - 0x0003FFFF Flash (256 KB)
0x20000000 - 0x20007FFF SRAM (32 KB)
0x40000000 - 0x400FFFFF Peripherals
0xE0000000 - 0xE0041FFF System Control
LM3S6965 (QEMU)¶
0x00000000 - 0x0003FFFF Flash (256 KB)
0x20000000 - 0x2000FFFF SRAM (64 KB) ← More RAM
0x40000000 - 0x400FFFFF Peripherals
0xE0000000 - 0xE0041FFF System Control
Peripheral Differences¶
UART Configuration¶
#ifdef PART_TM4C123GH6PM
// Hardware: Multiple UART modules
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
#elif defined(PART_LM3S6965)
// QEMU: Simplified UART
SYSCTL_RCGC1_R |= SYSCTL_RCGC1_UART0;
SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOA;
#endif
GPIO Differences¶
// TM4C: Advanced GPIO with multiple drive strengths
ROM_GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1,
GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
// LM3S: Basic GPIO configuration
GPIO_PORTA_DIR_R |= 0x02; // PA1 output
GPIO_PORTA_DEN_R |= 0x03; // PA0-1 digital enable
Timing and Clocks¶
Hardware Timing¶
void setup_system_clock_hw() {
// TM4C: Configure PLL for 80 MHz
ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL |
SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
}
QEMU Timing¶
void setup_system_clock_qemu() {
// LM3S: Simpler clock setup, timing not cycle-accurate
SYSCTL_RCC_R = SYSCTL_RCC_XTAL_8MHZ | SYSCTL_RCC_OSC_MAIN |
SYSCTL_RCC_USESYSDIV | (4 << SYSCTL_RCC_SYSDIV_S);
}
Interrupt Handling¶
Vector Table Differences¶
// tm4c_vectors.c
__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) = {
(void (*)(void))((uint32_t)&_stack_top),
ResetISR,
NmiSR,
FaultISR,
// ... TM4C-specific vectors
};
// lm3s_vectors.c
__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) = {
(void (*)(void))((uint32_t)&_stack_top),
ResetISR,
NmiSR,
HardFaultISR, // Different fault handling
// ... LM3S-specific vectors
};
Build Configuration¶
Compiler Flags¶
Hardware Build¶
set(CPU_FLAGS "-mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard")
add_compile_definitions(
PART_TM4C123GH6PM
TARGET_IS_TM4C123_RB1
ARM_MATH_CM4
)
QEMU Build¶
set(CPU_FLAGS "-mcpu=cortex-m3 -mthumb")
add_compile_definitions(
PART_LM3S6965
TARGET_IS_DUSTDEVIL_RA0
QEMU_BUILD
)
Linker Scripts¶
Hardware Linker Script¶
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
}
QEMU Linker Script¶
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K /* More RAM */
}
Platform-Specific Code¶
Conditional Compilation¶
void platform_init() {
#ifdef QEMU_BUILD
// QEMU-specific initialization
qemu_uart_init();
qemu_timer_init();
#else
// Hardware initialization
hw_clock_init();
hw_uart_init();
hw_gpio_init();
#endif
}
Feature Detection¶
typedef struct {
bool has_fpu;
bool has_mpu;
uint32_t sram_size;
uint32_t flash_size;
} platform_features_t;
platform_features_t get_platform_features() {
platform_features_t features = {0};
#ifdef PART_TM4C123GH6PM
features.has_fpu = true;
features.has_mpu = true;
features.sram_size = 32 * 1024;
#elif defined(PART_LM3S6965)
features.has_fpu = false;
features.has_mpu = true;
features.sram_size = 64 * 1024;
#endif
return features;
}
Testing Considerations¶
QEMU-Specific Testing¶
class QEMUTestBase(LabTestBase):
def setUp(self):
super().setUp()
# QEMU-specific setup
self.qemu_monitor = self.setup_qemu_monitor()
def inject_fault(self):
# QEMU allows fault injection
self.qemu_monitor.send("system_reset")
Hardware Testing¶
class HardwareTestBase(LabTestBase):
def setUp(self):
super().setUp()
# Hardware-specific setup
self.serial = serial.Serial('/dev/ttyUSB0', 115200)
self.openocd = self.setup_openocd()
Performance Implications¶
Execution Speed¶
- Hardware: Real-time, cycle-accurate
- QEMU: ~10-100x slower, not cycle-accurate
Memory Access¶
- Hardware: Wait states, cache effects
- QEMU: Uniform access times
Interrupt Latency¶
- Hardware: Deterministic, 12 cycles
- QEMU: Variable, depends on host
Best Practices¶
1. Abstract Platform Differences¶
// Use SDK functions that handle platform differences
embsec_uart_init(); // Handles both TM4C and LM3S
2. Test on All Platforms¶
# Test on QEMU
cmake --preset qemu && cmake --build build-qemu
./build-qemu/labs/buffer-overflow/test_lab.py
# Test on hardware
cmake --preset embedded && cmake --build build
make flash-buffer-overflow
3. Document Platform-Specific Behavior¶
/**
* @note On TM4C hardware, this function uses hardware FPU.
* On LM3S/QEMU, software floating-point is used.
*/
float calculate_checksum(const uint8_t *data, size_t len);
4. Provide Platform-Specific Workarounds¶
#ifdef QEMU_BUILD
// QEMU workaround for missing peripheral
#define READ_TIMER() (qemu_timer_read())
#else
// Hardware timer read
#define READ_TIMER() (TIMER0->TAR)
#endif
Migration Guide¶
Porting from LM3S to TM4C¶
- Update peripheral initialization
- Adjust memory layout if needed
- Enable FPU for floating-point
- Update interrupt vectors
Porting from TM4C to LM3S¶
- Remove FPU-dependent code
- Simplify peripheral usage
- Adjust for larger RAM
- Update build configuration
Debugging Platform Issues¶
Common Issues¶
- Different behavior in QEMU vs hardware
- Check timing-dependent code
- Verify peripheral initialization
-
Compare memory layouts
-
Build failures for specific platform
- Verify toolchain configuration
- Check conditional compilation
-
Review linker scripts
-
Runtime crashes on one platform
- Check stack usage (different RAM sizes)
- Verify interrupt handlers
- Review platform-specific code
Debug Strategies¶
# GDB commands for platform debugging
(gdb) info registers
(gdb) x/10x $sp
(gdb) disassemble $pc-32,$pc+32
(gdb) info mem
Future Platform Support¶
Planned platform additions:
- STM32F4 series
- nRF52 series
- RISC-V embedded
- Additional QEMU machines