# 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
