7.4 KiB
7.4 KiB
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
flowchart TD
%% --- STILI ---
classDef hw fill:#ffcccc,stroke:#333,stroke-width:2px;
classDef memory fill:#e1f5fe,stroke:#333,stroke-width:1px;
classDef logic fill:#fff9c4,stroke:#333,stroke-width:1px;
Start((START)) --> Init
%% --- BLOCCO INIZIALIZZAZIONE ---
subgraph Init ["1. Inizializzazione Bare Metal"]
direction TB
RCC["RCC AHB4ENR & APB1ENR\nAbilita Clock GPIO & USART"]:::hw
GPIO["GPIO MODER & AFR\nButton=Input, LED=Output, TX=AF"]:::hw
UART["USART3 CR1 & BRR\nConfigura Baud & Abilita UE"]:::hw
NVIC["NVIC_EnableIRQ\nAbilita Interrupts al processore"]:::hw
RCC --> GPIO --> UART --> NVIC
end
Init --> MainLoop
%% --- BLOCCO MAIN LOOP ---
subgraph Main ["2. Main Loop (Polling Button)"]
direction TB
MainLoop(while 1)
ReadIDR["Leggi GPIOC->IDR\n(Stato Bottone)"]:::hw
Debounce[Debounce Delay]:::logic
EdgeCheck{"Rising Edge?\n(Curr=1 && Prev=0)"}:::logic
ToggleOps[Toggle Logic]:::memory
UpdatePrev[Prev = Curr]:::logic
MainLoop --> ReadIDR --> EdgeCheck
EdgeCheck -- NO --> UpdatePrev
EdgeCheck -- SI --> ToggleOps
subgraph Toggle ["Logica XOR LED"]
ReadODR["Leggi GPIOB->ODR"]:::hw
XOR["Calcola: ODR ^ LED_MASK"]:::logic
WriteODR["Scrivi GPIOB->ODR"]:::hw
ReadODR --> XOR --> WriteODR
end
ToggleOps --> UpdatePrev
UpdatePrev --> Debounce --> MainLoop
end
%% --- BLOCCO INTERRUPT ---
subgraph ISR ["3. USART3 IRQ Handler"]
direction TB
Trigger((IRQ))
CheckTXE{"Flag TXE?\n(Data Reg Empty)"}:::logic
CheckTC{"Flag TC?\n(Tx Complete)"}:::logic
LoadDR["Scrivi USART3->DR\n(Invia Byte)"]:::hw
EnableTC["Abilita TCIE\nDisabilita TXEIE"]:::hw
DisableTC["Disabilita TCIE\nClear TC Flag"]:::hw
FreeBusy[Set tx_busy = 0]:::memory
Trigger --> CheckTXE
CheckTXE -- "SI: Buffer Pieno" --> LoadDR
CheckTXE -- "SI: Buffer Finito" --> EnableTC
CheckTXE -- NO --> CheckTC
CheckTC -- "SI: Fine Trasmissione" --> DisableTC --> FreeBusy
CheckTC -- NO --> Return((RTI))
end
%% --- CONNESSIONI LOGICHE ---
WriteODR -.-> |"Opzionale: Avvia TX"| Trigger
flowchart TD
%% --- DEFINIZIONE CLASSI GRAFICHE ---
classDef userFill fill:#e1f5fe,stroke:#0277bd,stroke-width:2px;
classDef stmFill fill:#fff9c4,stroke:#fbc02d,stroke-width:2px;
classDef pcFill fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px;
classDef term fill:#212121,color:#fff,stroke:#000;
%% --- CORSIA 1: UTENTE ---
subgraph User ["👤 Utente (Mondo Fisico)"]
direction TB
Start((Inizio))
PressBtn["Premi Bottone Blu"]:::userFill
CheckLeds["Osserva i LED"]:::userFill
CheckPC["Leggi Terminale PC"]:::userFill
end
%% --- CORSIA 2: STM32 (FIRMWARE) ---
subgraph STM32 ["⚙️ STM32 H7 (Bare Metal)"]
direction TB
Polling("Ciclo While Infinito"):::stmFill
IsPressed{"Rilevato\nFronte Salita?"}:::stmFill
ToggleAction["XOR Toggle LEDs\n(ODR ^ Mask)"]:::stmFill
LoadBuffer["Carica Buffer TX\nAbilita TXE IE"]:::stmFill
subgraph ISR ["Interrupt Service Routine"]
direction TB
SendByte["Hardware Invia Byte"]:::stmFill
CheckDone{"Finito?"}:::stmFill
end
end
%% --- CORSIA 3: PC (SOFTWARE) ---
subgraph PC ["💻 PC (Arch Linux + Julia)"]
direction TB
Listen{"Script Julia\nIn ascolto"}:::pcFill
ReceiveData["Ricezione Byte\n(/dev/ttyACM0)"]:::pcFill
PrintTerm["> Stampa a Video"]:::term
end
%% --- COLLEGAMENTI ---
%% Flusso Utente -> STM32
Start --> PressBtn
PressBtn -- "Pressione fisica" --> Polling
%% Logica STM32
Polling --> IsPressed
IsPressed -- No --> Polling
IsPressed -- Si --> ToggleAction
ToggleAction --> LoadBuffer
LoadBuffer -.-> |"Trigger IRQ"| SendByte
SendByte --> CheckDone
CheckDone -- No --> SendByte
CheckDone -- Si --> Polling
%% Feedback Visivo (STM32 -> Utente)
ToggleAction -.-> |"Luce LED"| CheckLeds
%% Comunicazione Seriale (STM32 -> PC)
SendByte == "Cavo USB (Serial)" ==> ReceiveData
%% Logica PC
Listen --> ReceiveData
ReceiveData --> PrintTerm
%% Feedback Terminale (PC -> Utente)
PrintTerm -.-> |"Lettura"| CheckPC
CheckPC --> PressBtn
flowchart TD
%% --- STILI ---
classDef cpu fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
classDef tim fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
classDef adc fill:#fff9c4,stroke:#fbc02d,stroke-width:2px
classDef dma fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef mem fill:#eeeeee,stroke:#616161,stroke-width:2px,stroke-dasharray: 5 5
%% --- CORSIA 1: CPU (INIZIALIZZAZIONE) ---
subgraph Setup ["1. INIZIALIZZAZIONE (CPU)"]
direction TB
InitDMA["DMA Setup:\n- Mode: CIRC (Circolare)\n- PData: ADC_DR\n- MData: Buffer[0]\n- Size: 128\n- Incr: Memory (MINC)"]:::cpu
InitADC["ADC Setup:\n- Conv: Single/Continuous\n- Trig: External (Timer)\n- DMA: Enable (Circular)"]:::cpu
InitTIM["TIM Setup:\n- Periodo: Freq Campionamento\n- Master Mode (MMS): Update (TRGO)"]:::cpu
StartAll["START:\n1. ADC_CR |= ADEN\n2. DMA_SxCR |= EN\n3. ADC_CR |= ADSTART\n4. TIM_CR1 |= CEN"]:::cpu
InitDMA --> InitADC --> InitTIM --> StartAll
end
StartAll --> LoopTIM
%% --- CORSIA 2: HARDWARE AUTOMATICO ---
subgraph Hardware ["2. LOOP HARDWARE (Senza CPU)"]
direction TB
%% TIM
LoopTIM(Timer Conta):::tim
EventUpdate{"Update Event?\n(CNT == ARR)"}:::tim
TriggerTRGO["Output TRGO\n(Hardware Signal)"]:::tim
LoopTIM --> EventUpdate
EventUpdate -- NO --> LoopTIM
EventUpdate -- SI --> TriggerTRGO
%% ADC
TriggerTRGO --> ADC_Start["ADC Avvia Conv.\n(EXTEN rising)"]:::adc
ADC_Conv[Campionamento...]:::adc
FlagEOC{"Fine Conv?\n(ISR & EOC)"}:::adc
ADC_Start --> ADC_Conv --> FlagEOC
%% DMA
FlagEOC -- SI --> DMA_Req["Richiesta DMA\n(ADC -> DR)"]:::dma
DMA_Move["Sposta Dato:\nADC_DR -> Buffer[idx]"]:::dma
DMA_Inc["Incrementa idx:\nidx = (idx + 1) & 127"]:::dma
DMA_Req --> DMA_Move --> DMA_Inc
%% BUFFER
BufferState{"Buffer Pieno/Metà?\n(TCIF / HTIF)"}:::mem
DMA_Inc --> BufferState
BufferState -- "Ancora spazio" --> LoopTIM
end
%% --- CORSIA 3: INTERRUPT DMA (CPU) ---
subgraph IRQ ["3. ELABORAZIONE (CPU - Interrupt DMA)"]
direction TB
CheckFlag{"Quale Flag DMA?"}:::cpu
TaskHT["Half Transfer (HTIF):Elabora prima metà (0-63)"]:::cpu
TaskTC["Transfer Complete (TCIF):\nElabora seconda metà (64-127)"]:::cpu
Clear["Clear Flags:\nDMA_LIFCR / HIFCR"]:::cpu
BufferState -.-> |"IRQ Trigger"| CheckFlag
CheckFlag --> |HTIF| TaskHT
CheckFlag --> |TCIF| TaskTC
TaskHT --> Clear
TaskTC --> Clear
end