325 lines
9.5 KiB
Markdown
325 lines
9.5 KiB
Markdown
# SXXXXXXX_PyDownloadFwViaSRIO - Manuale Italiano
|
||
|
||
## Introduzione
|
||
Applicazione per il download del firmware su FPGA tramite protocollo SRIO over TFTP. Il software permette di eseguire operazioni di cancellazione, scrittura e verifica della memoria flash di dispositivi FPGA Xilinx collegati via SRIO.
|
||
|
||
## Installazione
|
||
|
||
### Requisiti
|
||
- Python 3.8 o superiore
|
||
- Windows/Linux
|
||
- Accesso di rete all'hardware target
|
||
|
||
### Installazione da Repository
|
||
1. Clona il repository: `git clone <repository_url>`
|
||
2. Naviga nella directory del progetto: `cd SXXXXXXX_PyDownloadFwViaSRIO`
|
||
3. Crea un ambiente virtuale (raccomandato):
|
||
```bash
|
||
python -m venv .venv
|
||
.venv\Scripts\activate # Windows
|
||
source .venv/bin/activate # Linux
|
||
```
|
||
4. Installa le dipendenze: `pip install -r requirements.txt`
|
||
|
||
## Utilizzo
|
||
|
||
### Avvio dell'Applicazione
|
||
Per eseguire l'applicazione con interfaccia grafica:
|
||
```bash
|
||
python -m pydownloadfwviasrio
|
||
```
|
||
|
||
### Interfaccia Grafica
|
||
|
||
#### Selezione Target
|
||
1. **Combobox "Target FPGA"**: Seleziona l'FPGA target dalla lista configurata
|
||
2. **Pulsante "⚙️ Manage Configuration"**: Apre il dialog di gestione configurazione (IP, modelli, target)
|
||
|
||
#### Pannello Informazioni Target
|
||
Mostra le informazioni del target selezionato:
|
||
- Nome e descrizione target
|
||
- Indirizzo SRIO slot
|
||
- Architettura e modello FPGA
|
||
- Tipo di flash e indirizzamento
|
||
- Numero di settori
|
||
- Percorsi file golden e user binary
|
||
|
||
#### Pulsanti Operazioni
|
||
|
||
##### 🗑️ Erase (Cancellazione)
|
||
Cancella un'area della flash memory:
|
||
- Inserire indirizzo iniziale e finale in formato esadecimale (es. `0x00000000`, `0x00FFFFFF`)
|
||
- La cancellazione avviene per settori da 64KB
|
||
- **Tempo stimato**: ~2-3 secondi per settore (es. 16MB = ~8 minuti)
|
||
|
||
##### ✍️ Write (Scrittura)
|
||
Scrive un file binario nella flash:
|
||
1. Seleziona il file binario da scrivere (.bin, .bit, ecc.)
|
||
2. Inserire l'indirizzo di destinazione
|
||
3. La scrittura avviene in blocchi da 256 bytes
|
||
4. **Tempo stimato**: ~5-10 secondi per MB (es. 16MB = ~2-3 minuti)
|
||
|
||
##### 🔍 Verify (Verifica)
|
||
Verifica che il contenuto della flash corrisponda al file:
|
||
1. Seleziona il file binario di riferimento
|
||
2. Inserire l'indirizzo da verificare
|
||
3. Il confronto avviene in chunk configurabili (default 4KB)
|
||
4. **Tempo stimato**: ~3-5 secondi per MB
|
||
|
||
##### 🔄 Full Sequence (Sequenza Completa)
|
||
Esegue automaticamente la sequenza completa:
|
||
1. **Erase** dell'area necessaria (dimensione file arrotondata a 64KB)
|
||
2. **Write** del file binario
|
||
3. **Verify** automatica del contenuto scritto
|
||
|
||
Questa è l'opzione **raccomandata** per programmazione completa della flash.
|
||
|
||
##### 🛑 ABORT (Interruzione Operazione)
|
||
**Nuova funzionalità**: Permette di interrompere un'operazione in corso.
|
||
|
||
- **Quando è disponibile**: Il pulsante diventa attivo (rosso) durante qualsiasi operazione lunga (Erase, Write, Verify, Full Sequence)
|
||
- **Come utilizzarlo**: Cliccare sul pulsante durante l'operazione
|
||
- **Cosa succede**:
|
||
- L'operazione si interrompe **quasi istantaneamente** (< 2ms)
|
||
- Viene visualizzato il messaggio "❌ Operation aborted by user"
|
||
- I controlli tornano allo stato normale
|
||
- La flash rimane nello stato raggiunto (es. se interrotto durante write, solo i blocchi scritti fino a quel momento sono programmati)
|
||
|
||
- **Casi d'uso tipici**:
|
||
- File sbagliato selezionato
|
||
- Indirizzo errato inserito
|
||
- Operazione troppo lunga (es. erase completa non necessaria)
|
||
- Target sbagliato selezionato
|
||
- Test e debug
|
||
|
||
**⚠️ Attenzione**: Dopo un abort durante una Full Sequence, la flash potrebbe essere in uno stato inconsistente (es. cancellata ma non scritta). Ripetere l'operazione completa per garantire consistenza.
|
||
|
||
#### Barra di Progresso
|
||
Durante le operazioni viene mostrata:
|
||
- Percentuale di completamento
|
||
- Barra visuale del progresso
|
||
- Possibilità di abort in qualsiasi momento
|
||
|
||
#### Log Operazioni
|
||
Il pannello "General Log" mostra in tempo reale:
|
||
- Comandi TFTP inviati (SRIO read/write)
|
||
- Stato delle operazioni (inizializzazione, erase, write, verify)
|
||
- Errori e retry automatici
|
||
- Risultato finale (✅ successo / ❌ fallimento / ⚠️ abort)
|
||
|
||
#### TFTP Commands
|
||
Il pannello "TFTP Commands" mostra i dettagli tecnici:
|
||
- Comandi TFTP grezzi con parametri
|
||
- Retry e timeout
|
||
- Messaggi di debug a basso livello
|
||
|
||
### Configurazione Target
|
||
|
||
La configurazione dei target può essere gestita in due modi:
|
||
|
||
#### 1. File JSON (flash_profiles.json)
|
||
Formato moderno strutturato:
|
||
```json
|
||
{
|
||
"global_config": {
|
||
"ip": "192.168.2.102",
|
||
"port": 50069,
|
||
"srio_base": 0,
|
||
"fpga_base": 0,
|
||
"fpga_sector": 256,
|
||
"default_target": "EIF_FPGA1"
|
||
},
|
||
"models": {
|
||
"xcku040": {
|
||
"id_model": 0,
|
||
"model": "xcku040",
|
||
"num_sectors": 256,
|
||
"flash_type": 0,
|
||
"is_4byte_addressing": true,
|
||
...
|
||
}
|
||
},
|
||
"targets": {
|
||
"EIF_FPGA1": {
|
||
"id_target": "EIF_FPGA1",
|
||
"slot_address": "0x13",
|
||
"architecture": "Xilinx",
|
||
"id_model": 0,
|
||
...
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2. File INI (targets.ini) - Legacy
|
||
Formato compatibile con versione C++:
|
||
```ini
|
||
[GLOBAL]
|
||
ip=192.168.2.102
|
||
port=50069
|
||
...
|
||
|
||
[MODEL_xcku040]
|
||
id_model=0
|
||
num_sectors=256
|
||
...
|
||
|
||
[TARGET_EIF_FPGA1]
|
||
id_target=EIF_FPGA1
|
||
slot_address=0x13
|
||
id_model=0
|
||
...
|
||
```
|
||
|
||
### Dialog Gestione Configurazione
|
||
Accessibile tramite pulsante "⚙️ Manage Configuration":
|
||
|
||
#### Tab "Global Configuration"
|
||
- Indirizzo IP del sistema target
|
||
- Porta TFTP
|
||
- Parametri SRIO (base address, sector size)
|
||
- Target di default
|
||
|
||
#### Tab "Models"
|
||
- Lista dei modelli FPGA configurati
|
||
- Pulsanti per aggiungere/modificare/eliminare modelli
|
||
- Proprietà modello: tipo flash, settori, indirizzamento, aree memoria
|
||
|
||
#### Tab "Targets"
|
||
- Lista dei target FPGA disponibili
|
||
- Associazione target → modello
|
||
- Slot address SRIO specifico per ogni target
|
||
- Percorsi file binari (golden/user)
|
||
|
||
Tutte le modifiche vengono salvate automaticamente in `flash_profiles.json`.
|
||
|
||
## Sviluppo
|
||
|
||
### Struttura del Codice
|
||
|
||
```
|
||
pydownloadfwviasrio/
|
||
├── __init__.py # Package initialization
|
||
├── __main__.py # Entry point (avvia GUI)
|
||
├── profiles.py # Gestione profili/configurazione
|
||
├── tftp_client.py # Client TFTP per SRIO transport
|
||
├── core/
|
||
│ ├── core.py # Business logic (FirmwareFlasher)
|
||
│ └── srio_flash.py # Hardware controller (SRIOFlashController)
|
||
└── gui/
|
||
└── gui.py # Interfaccia grafica Tkinter
|
||
```
|
||
|
||
### Architettura ABORT
|
||
|
||
Il meccanismo di abort è implementato a tre livelli:
|
||
|
||
#### 1. Livello GUI (`gui.py`)
|
||
```python
|
||
# Flag globale
|
||
self.abort_requested = False
|
||
|
||
# Callback di controllo
|
||
def _check_abort(self) -> bool:
|
||
if self.abort_requested:
|
||
return True
|
||
return False
|
||
|
||
# Handler pulsante
|
||
def _abort_operation(self) -> None:
|
||
self.abort_requested = True
|
||
```
|
||
|
||
#### 2. Livello Business Logic (`core.py`)
|
||
```python
|
||
def erase_area(self, ..., abort_check: Optional[Callable[[], bool]] = None) -> bool:
|
||
# Propaga callback al controller hardware
|
||
self.flash_controller.set_abort_check(abort_check)
|
||
|
||
try:
|
||
for sector in sectors:
|
||
# Controlla abort tra settori
|
||
if abort_check and abort_check():
|
||
return False
|
||
# ... erase sector ...
|
||
finally:
|
||
# Cleanup sempre eseguito
|
||
self.flash_controller.set_abort_check(None)
|
||
```
|
||
|
||
#### 3. Livello Hardware (`srio_flash.py`)
|
||
```python
|
||
def _write_reg(self, ...) -> bool:
|
||
for attempt in range(retries):
|
||
# Controlla abort prima di ogni retry
|
||
if self.abort_check and self.abort_check():
|
||
return False
|
||
# ... write and verify ...
|
||
|
||
def _wait_status_bit(self, ...) -> bool:
|
||
for i in range(max_retries):
|
||
# Controlla abort prima di ogni poll
|
||
if self.abort_check and self.abort_check():
|
||
return False
|
||
# ... poll status ...
|
||
```
|
||
|
||
**Punti chiave**:
|
||
- L'abort è verificato in **ogni loop critico** (retry, polling, iterazioni)
|
||
- Risposta quasi istantanea (< 2ms)
|
||
- Cleanup garantito tramite `try/finally`
|
||
- Nessun impatto su performance (controllo inline lightweight)
|
||
|
||
### Come Eseguire i Test
|
||
|
||
```bash
|
||
# Test conversione profili
|
||
python tools/test_conversion.py
|
||
|
||
# Test TFTP logging
|
||
python tools/test_tftp_logging.py
|
||
|
||
# Test esempio utilizzo profili
|
||
python tools/example_profile_usage.py
|
||
```
|
||
|
||
### Debug
|
||
|
||
Per abilitare logging dettagliato, modificare in `gui.py`:
|
||
```python
|
||
# Mostra tutti i comandi TFTP nel log
|
||
log=self._append_log # invece di log=None
|
||
```
|
||
|
||
## Risoluzione dei Problemi
|
||
|
||
### "TFTP timeout" o "No response"
|
||
- Verificare connettività di rete (ping IP target)
|
||
- Controllare firewall Windows/Linux (porta UDP 50069)
|
||
- Verificare che l'hardware target sia acceso e configurato
|
||
|
||
### "Write verify FAILED after 500 attempts"
|
||
- Possibile problema hardware (flash danneggiata)
|
||
- Verificare alimentazione stabile
|
||
- Tentare re-inizializzazione QSPI
|
||
|
||
### "Operation aborted by user" apparire spontaneamente
|
||
- Non dovrebbe accadere - verificare che il pulsante ABORT non sia stato premuto accidentalmente
|
||
- Se il problema persiste, segnalare come bug
|
||
|
||
### Operazione troppo lenta
|
||
- **Erase**: Normale, ~2-3 sec/settore (hardware limitation)
|
||
- **Write**: Normale, ~5-10 sec/MB
|
||
- **Verify**: Normale, ~3-5 sec/MB
|
||
- Se significativamente più lento: verificare congestione di rete
|
||
|
||
### File binario non trovato
|
||
- Verificare che il percorso in "Golden Binary" / "User Binary" sia corretto
|
||
- Usare percorsi assoluti o relativi alla directory di esecuzione
|
||
- Verificare permessi di lettura del file
|
||
|
||
### "Target not found" all'avvio
|
||
- Verificare che `flash_profiles.json` esista nella directory root
|
||
- Controllare sintassi JSON con un validator
|
||
- Rigenerare il file con `tools/convert_ini_to_json.py` se necessario
|