Le nuove tecnologie rendono sempre più necessario il ricorso a strumenti che ci permettano di acquisire, da un lato, una perfetta padronanza dei flussi di lavoro e nel contempo, dall’altro, di apprezzare nel più breve tempo possibile le caratteristiche tecniche dei prodotti stessi. Code Composer Studio cerca di offrire una risposta concreta ad entrambi gli aspetti.
Introduzione
Texas Instruments, in linea con la sua missione, offre da molti anni un vero “tavolo di lavoro” in grado di proporre, in un’unica interfaccia, diversi strumenti perfettamente integrati. Questo particolare approccio permette a tutti gli utilizzatori di acquisire, in modo rapido, la perfetta padronanza delle nuove tecnologie e, allo stesso tempo, di poter sfruttare in modo immediato e rapido le caratteristiche tecniche dei nuovi processori. Il Code Composer Studio (CCS) di Texas Instruments è perfettamente integrato in una varietà interessante di processori: dalla famiglia MSP430 ai nuovi ARM fino a comprendere anche la collaudata famiglia dei DSP o Digital Signal Processor. Possiamo certamente affermare che CCS è apprezzabile ambiente integrato per lo sviluppo e la verifica di programmi software per differenti piattaforme hardware come, ad esempio, schede DSP.
Code Composer Studio è un software versatile e corredato da una discreta manualistica insieme a un tutorial per acquisire i primi veloci rudimenti. Come per la maggior parte di questi tool disponibili in commercio, Code Composer Studio è un vero IDE integrato che permette di passare nelle diverse fasi del progetto al semplice tocco del mouse. Il linguaggio di riferimento utilizzato è il C, anche se permette di scrivere le proprie applicazioni in forme differenti come l’assembler dei processori di riferimento consentendo di utilizzare istruzioni specifiche. Il codice correttamente compilato genera un file con estensione out che può essere trasferito ed eseguito nelle memorie del calcolatore oppure inserito nelle memorie della scheda attraverso opportuni programmi per la sua scrittura su dispositivi di tipo EEPROM. Strumenti già presenti comunque nel software fornito dalla casa costruttrice Texas Instruments.
IL SISTEMA DI SCRIPTING
Con Code Composer Studio è possibile utilizzare un meccanismo basato sugli script consentendo di attivare, ad esempio, alcune funzionalità in modo trasparente. Infatti, attraverso il suo ambiente integrato, o IDE, il Code Composer Studio fornisce una libreria di comandi integrati con Javascript o Perl utili, ad esempio, se volessimo invocare sessioni di debug. Non solo, con il suo debug server scripting, o DSS, è anche possibile - sempre ricorrendo a particolari API offerte dal costruttore quale Javascript via Rhino o Python con Jython - allo scopo di garantire una maggiore flessibilità, eseguire scripting code anche fuori dal tool di lavoro e senza la necessità di particolari configurazioni. Allo scopo di mostrare questa particolarità, Code Composer Studio contiene un semplice script: questo script permette il caricamento e l'esecuzione di un programma. Per lanciare questo script, “LoadProgram.js”, occorre, una volta che si è entrato a livello di prompt, in Windows, o shell se Unix, posizionarsi in <ccs install root >/ccsv5/ ccs_base/scripting/examples/Debug- ServerExamples e inserire il comando:
In Windows - ..\..\bin\dss LoadProgram. js In Linux - ../../bin/dss LoadProgram.js
Possiamo, a questo punto, notare che lo script “LoadProgram.js” è simile ai diversi script che possiamo scrivere e lanciare nell’apposita finestra di “CCS Scripting Console” con diverse piccole e insignificanti differenze: la chiamata alla classe ScriptingEnvironment permette di creare l’oggetto DebugServer utilizzato al pari quando utilizziamo la finestra CCS Scripting Console e, infine, con la direttiva import <package> ci garantisce la possibilità di includere qualsiasi package Java che ci risulta utile. La forma più comune è, però, quella dove lo script è invocato direttamente nella finestra della console associata. Questo script può contenere una lista di comandi DSS che possono essere eseguiti direttamente in “CCS Scripting console”. Per fare questo è necessario creare prima un file di testo, myscript.js, e inserire tutti i vostri comandi come in questo esempio:
ds.setConfig( <Path/to/target/ccxml/file> ); var debugSession = ds.openSession(“.*”); debugSession.memory.loadProgram( <Path/to/out/file > ); debugSession.target.run();
Al termine è necessario eseguire il comando loadJSFile sempre nella solita console per caricare ed eseguire lo script, in altre parole loadJSFile(“c:/ Temp/myscript.js”). La console, CCS Scripting Console, è aperta ricorrendo a ‘View->Scripting Console’ dal menu principale. Per utilizzare le diverse API che Code Composer mette a disposizione occorre interagire in questo modo. Per prima cosa occorre impostare il device configuration o ccxml, così: ds.setConfig(“C:/ Temp/my_device.ccxml”), successivamente è necessario aprire una sessione di debug con var debugSession = ds.openSession(“.*”) e, solo in seguito, caricare il programma con debugSession. memory.loadProgram(“C:/ Temp/my_program.out”). In ultima istanza è necessario, poi, lanciare ed eseguire il programma con debugSession. target.run().
UTILIZZARE JAVASCRIPT
Per utilizzare le prerogative di Javascript è necessario configurare l’ambiente DSS. Ovvero, è necessario impostare, ad esempio, le variabili d’ambiente e le classpaths. Al fine di facilitare l’utente finale, all’interno dell’ambiente di lavoro esiste uno script, invocato a livello di shell o batch, che permette di configurare l’intero ambiente. Questo script si trova nella cartella di installazione, o più precisamente è possibile trovarlo in ’<INSTALL DIR>\ ccsv4\scripting\bin’ (CCSv4), ‘<INSTALL DIR>\ccsv5\ccs_base\scripting\ bin’ (CCSv5) o ‘<INSTALL DIR>\ccsv6\ ccs_base\scripting\bin (CCSv6)’, a seconda della versione di Code Composer Studio in uso. Ricordiamo che il file ha l’estensione .bat se ci trovassimo in ambiente Windows o .sh in Linux (dss.bat o dss.sh). Il file deve essere lanciato passandogli alcuni parametri: > dss myscript.js scriptParam1 scriptParam2
Non solo, siccome ogni script è, in sostanza, un piccolo programma Javascript e, di conseguenza, non immune a errori, all’interno di Code Composer Studio si trova anche un debugger (Rhino Debugger). Questo debugger dispone di un’interfaccia grafica che permette una facile interazione con il proprio script: è possibile inserire un breakpoint o vedere le variabili utilizzate. A questo proposito la Figura 1 mostra come si presenta all’utente finale.
Per utilizzare questo debugger con i vostri scripts, nella versione 6 è necessario: > dss.bat -dss.debug myScript.js
Mentre nella versione 5.2, una volta aperto dss.bat, è necessario sostituire %RHINO_ SHELL% con %RHINO_DEBUGGER%, così, da:
java.exe -Xms40m -Xmx256m -Dxpcom. bridge.executeOnDedicatedThread=yes -Dorg.eclipse.swt.browser.XULRunnerPath=”% DEBUGSERVER%\win32” -DXPCOM.RUNTIME=”% DEBUGSERVER%\win32” -cp %RHINO_ JAR%;%SCRIPTING_JARS% %RHINO_SHELL% % 1 %2 %3 %4 %5 %6 %7 %8 %9
a
java.exe -Xms40m -Xmx256m -Dxpcom. bridge.executeOnDedicatedThread= yes -Dorg.eclipse.swt.browser.XULRunnerPath=”% DEBUGSERVER%\win32” -DXPCOM.RUNTIME=”%DEBUGSERVER%\win32” -cp %RHINO_JAR%;%SCRIPTING_JARS% %RHINO_ DEBUGGER% %1 %2 %3 %4 %5 %6 %7 %8 %9
In buona sostanza, basterebbe, se vi fossero continue sessioni di debug, creare una versione ad-hoc del file. Non solo, a volte, come indica il costruttore, il lavoro che compie Rhino Debugger potrebbe essere insufficiente, o meglio, Texas Instruments, allo scopo di agevolare la sessione di verifica a livello di script e fornire ulteriori strumenti d’indagine, assicura una maggiore flessibilità al debugger tanto da offrire una sessione di lavoro più efficiente. Questo è fatto associando una sessione di debug a DSS. Al fine di agevolarne l’uso, il costruttore ha corredato alla sezione DSS del Code Composer Studio diversi esempi. Questi possono essere, in base alle differenti versioni del tool di lavoro, trovati in:
CCSv4: <INSTALL DIR>\ccsv4\scripting\ examples CCSv5: <INSTALL DIR>\ccsv5\ccs_base\ scripting\examples CCSv6: <INSTALL DIR>\ccsv6\ccs_base\ scripting\examples
Questi esempi intendono offrire al progettista tutte le informazioni che possono essere utili alla stesura di script di debug e abbracciano tutti i vari aspetti del lavoro quotidiano. Ad esempio, con DebugServerExamples, si intende permettere di impostare una sessione di debug, comprensivo del simulatore, dalle viste delle memorie fino all’inserimento dei breakpoints: per lanciare questo script è necessario eseguire il file batch “go.bat” presente in “.\ DebugServerExamples”. Non solo, con DVTExamples è possibile impostare il profile di funzioni o dati e anche per questo è necessario eseguire “go.bat” in “.\ DVTExamples”. Infine, con loadti è possibile gestire una sessione di lavoro, ovvero verifica e messa a punto del codice, con un target (un simulatore o una piattaforma hardware), mentre con Testserver il progettista può sfruttare il protocollo TCP/IP nel suo lavoro controllando una sessione di verifica da remoto. Come vediamo, le possibilità sono diverse e dipendono, per la maggior parte, dal C6000 o, in altre parole, dai differenti elementi presenti nell’ambiente integrato. È possibile sfruttare, nel modo più lato possibile del termine, il Code Composer Studio ricorrendo alle API che il sistema offre. La documentazione, come al solito, è disponibile nell’ambiente di lavoro in base alla versione in uso; infatti:
CCSv4: <INSTALL DIR>\ccsv4\scripting\ docs\GettingStarted.htm CCSv5: <INSTALL DIR>\ccsv5\ccs_base\ scripting\docs\GettingStarted.htm CCSv6: <INSTALL DIR>\ccsv6\ccs_base\ scripting\docs\GettingStarted.htm
Altro aspetto da non sottovalutare è la possibilità di ricorrere alla forma interattiva attraverso la finestra “scripting console”. Un’attività da non trascurare è la necessità di, prima di iniziare una sessione di debug, configurare il nostro target; infatti, Texas Instruments assicura la presenza di un’API dedicata, setConfig(), che riceve in ingresso la configurazione in uso (un file .ccxml). Questo file può anche essere realizzato ricorrendo al “CCS Target Setup” tool. Come qualsiasi applicazione Java, anche in questo ambiente le eccezioni possono essere gestite attraverso uno script con la consueta JavaScript try-catch. Ovvero:
try { debugSession.memory.loadProgram(testProgFile); } catch (ex) { dssScriptEnv.traceWrite(testProgFile + “ does not exist! Aborting script”); quit(); }
Una caratteristica che, di solito, non si prende molto in considerazione è la possibilità di mettere a punto, e gestire, differenti sessioni di debug in un’architettura multi-core. Questo può essere fatto utilizzando la chiamata openSession() e specificare il nome della board e della CPU dove intendiamo iniziare una sessione di debug. Ad esempio, a questo riguardo Texas Instruments ci fornisce un esempio molto interessante basato su TCI6488 EVM con 6 C64x+ DSPs. Per prima cosa è necessario conoscere il nome esatto della piattaforma hardware di lavoro utilizzata nel file di configurazione e solo in seguito aprire la sessione di lavoro, openSession(), passando come argomento, ad esempio, il suo riferimento, così:
openSession(“TCI6488EVM_XDS510USB/ C64PLUS_F1A”);
Oppure, in alternativa, è possibile ricorrere al nome della board e della CPU: in questo apriremo una sessione singola di debug per una CPU configurata, così:
openSession(“TCI6488EVM_XDS510USB”, “C64PLUS_F1A”);
Insomma, le possibili combinazioni sono diverse. Il Listato 2 mostra uno script reale che utilizza la prima opzione.
from java.lang import * from java.util import * from com.ti.debug.engine.scripting import * from com.ti.ccstudio.scripting.environment import * # Create our scripting environment object - which is the main entry point into any script and # the factory for creating other Scriptable Servers and Sessions script = ScriptingEnvironment.instance() # Create a log file in the current directory to log script execution script.traceBegin(“dss_py.xml”, “DefaultStylesheet.xsl”) # Set our TimeOut script.setScriptTimeout(15000) # Log everything script.traceSetConsoleLevel(TraceLevel.ALL) script.traceSetFileLevel(TraceLevel.ALL) # Get the Debug Server and start a Debug Session debugServer = script.getServer(“DebugServer.1”) debugServer.setConfig(“tisim_c64xple.ccxml”); debugSession = debugServer.openSession() # Load program debugSession.memory.loadProgram(“modem.out”) # Set a breakpoint at “main” main = debugSession.symbol.getAddress(“main”) bp1 = debugSession.breakpoint.add(main) # Set another breakpoint address = debugSession.symbol.getAddress(“ReadNextData”) bp2 = debugSession.breakpoint.add(address) # Restart our Target debugSession.target.restart() # Run if already not automatically halted at main. Should halt at first BP if debugSession.expression.evaluate(“PC”) != main: debugSession.target.run() # Using an expression - get the current value of the PC nPC = debugSession.expression.evaluate(“PC”) # Verify we halted at the correct address. Use hex() to convert the # result to a hex string when logging messages if nPC == main: script.traceWrite(“SUCCESS: Halted at correct location”) else: script.traceWrite(“FAIL: Expected halt at “ + hex(address) + “, actually halted at “ + hex(nPC)) script.traceSetConsoleLevel(TraceLevel.INFO) script.traceWrite(“TEST FAILED!”) script.traceEnd() System.exit(1); # Run again. Should halt at our breakpoint debugSession.target.run() # Using an expression - get the current value of the PC nPC = debugSession.expression.evaluate(“PC”) # Verify we halted at the correct address. if nPC == address: script.traceWrite(“SUCCESS: Halted at correct location”) else: script.traceWrite(“FAIL: Expected halt at “ + hex(address) + “, actually halted at “ + hex(nPC)) script.traceSetConsoleLevel(TraceLevel.INFO) script.traceWrite(“TEST FAILED!”) script.traceEnd() System.exit(1); # All done debugSession.terminate() debugServer.stop()
Listato 1 - Esempio di script con Python |
... // Get the Debug Server and start a Debug Session debugServer = script.getServer(“DebugServer.1”); // Configure target for a TCI6488 EVM with SD XDS510 USB emulator script.traceWrite(“Configuring debug server for TCI6488 EVM...”); debugServer.setConfig(“TCI6488EVM_SD510USB.ccxml”); script.traceWrite(“Done!”); // Open a debug session for each TCI6488 CPU script.traceWrite(“Opening a debug session for all TCI6488 cores...”); debugSessionF1A = debugServer.openSession(“TCI6488EVM_XDS510USB/C64PLUS_ F1A”); debugSessionF1B = debugServer.openSession(“TCI6488EVM_XDS510USB/C64PLUS_ F1B”); debugSessionF1C = debugServer.openSession(“TCI6488EVM_XDS510USB/C64PLUS_ F1C”); debugSessionF2A = debugServer.openSession(“TCI6488EVM_XDS510USB/C64PLUS_ F2A”); debugSessionF2B = debugServer.openSession(“TCI6488EVM_XDS510USB/C64PLUS_ F2B”); debugSessionF2C = debugServer.openSession(“TCI6488EVM_XDS510USB/C64PLUS_ F2C”); script.traceWrite(“Done!”); // Connect to each TCI6488 CPU script.traceWrite(“Connecting to all TCI6488 CPUs...”); debugSessionF1A.target.connect(); debugSessionF1B.target.connect(); debugSessionF1C.target.connect(); debugSessionF2A.target.connect(); debugSessionF2B.target.connect(); debugSessionF2C.target.connect(); script.traceWrite(“Done!”); // Load a program for just the first TCI6488 CPU script.traceWrite(“Loading program to first TCI6488 CPU...”); debugSessionF1A.memory.loadProgram(“HelloTCI6488.out”); script.traceWrite(“Done!”); // Load a program for just the second TCI6488 CPU script.traceWrite(“Loading program to second TCI6488 CPU...”); debugSessionF1B.memory.loadProgram(“HelloTCI6488.out”); script.traceWrite(“Done!”); // Run the program for just the first TCI6488 CPU script.traceWrite(“Executing program on first TCI6488 CPU...”); debugSessionF1A.target.run(); script.traceWrite(“Execution complete!”); // Reload program for just the first TCI6488 CPU script.traceWrite(“Loading program to first TCI6488 CPU...”); debugSessionF1A.memory.loadProgram(“HelloTCI6488.out”); script.traceWrite(“Done!”); // Run the program for the first and second TCI6488 CPU simultaneously script.traceWrite(“Executing program on first and second TCI6488 CPU...”); var dsArray = new Array(); dsArray[0] = debugSessionF1A; dsArray[1] = debugSessionF1B; debugServer.simultaneous.run(dsArray); // Run CPUs 1 and 2 script.traceWrite(“Done!”); ...
Listato 2 - Sessione di debug con file di configurazione |
UTILIZZARE PYTHON
Oltre a Javascript, il nostro Code Composer Studio può anche utilizzare Python, o meglio una sua versione particolare chiamata Jython. Il costruttore, però, suggerisce una configurazione minima indispensabile per utilizzare Python, ovvero:
- CCSv5 (o maggiore)
- la più recente installazione di Jython
- la macchina virtuale di Java, 32-bit Java Runtime Environment (JRE)
È necessario impostare le diverse variabili d’ambiente come in questo modo, facendo attenzione che per <CCS BASE DIR> ci si deve riferire al percorso d’installazione del tool:
- <CCS BASE DIR>/DebugServer/packages/ti/dss/java/dss.jar
- <CCS BASE DIR>/DebugServer/packa-ges/ti/dss/java/com.ti.ccstudio.scripting.environment_3.1.0.jar
- <CCS BASE DIR>/DebugServer/packages/ti/dss/java/com.ti.debug.engine_1.0.0.jar
- <CCS BASE DIR>/dvt/scripting/dvt_scripting.jar
Al pari di ogni programma Python, le classi sono importate al solito modo, come: from com.ti.debug.engine.scripting import * from com.ti.ccstudio.scripting.environment import *
CONCLUSIONE
Il tool di Texas Instruments ha raggiunto, con le attuali versioni, un buon livello di maturità tanto da essere utilizzato in diverse applicazioni e contesti sapendo di offrire a un progettista hardware/firmware strumenti di lavoro flessibili e apprezzati.