Skip to content

Commit

Permalink
implementing target functions made it clear that some changes on SWD
Browse files Browse the repository at this point in the history
were needed also added some documentation.
  • Loading branch information
Lars Pötter committed Jan 15, 2024
1 parent bd86996 commit 221bc97
Show file tree
Hide file tree
Showing 18 changed files with 723 additions and 100 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
/*.sal
/bin
/.settings/
/*.ods
40 changes: 40 additions & 0 deletions doc/architecture.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,46 @@ The file sytem can be accessed using the USB interface (Mass Storage Device Clas

== structure

This chapter describes the structure of the component that make up the firmware, as well as their interactions.

These are the modules that make up the firmware:
- swd
- target
- gdbserver
- file system

The swd module provides the functionality of the SWD Interface (defined in probe_api/swd.h) to the target module.

The target module executes the functionality requested by the gdbserver module.

The gdbserver module implements the GDB-Server protocoll and uses the target module to aquire the requested information and to execute the commanded actions.

The file system provides the mass storage interface.

=== SWD

The SWD module implements the ARM specified two wire debug protocol. It does this in a layered approach.

==== bit layer
The first and lowest layer is the bit layer. It is implemented in swd_gpio.c and deals with the SWDIO and SWCLK signals. It handles the single bits on the wires. So high, Low Input Output,..

==== packet layer
The second layer is the packet layer it sits on top of the bit layer. It is implemented in swd_packets.c and handles packets. It knows how SWD packets lok like and sends the requested packets over the line. It does this asynchronous to the API function being called in the tick function. It uses a queue. The API call enters the request for a packet to be send into the queue. In the tick call the queu is checked and if it contains a request then one packet will be send. This process makes it necessary to collect the result of a read packet from a result queue.

==== protocol layer
On top of the packet layer is the protocol layer. It is implemented in swd_protocol.c and swd_engine.c. It provides an API(defined in probe_api/swd.h) for other modules (mainly the target module) to use. It also put the requested actions into a queue and executes them once the tick function gets called.

=== Target

The target module implements the interface to exactly one chip.

=== GDB Server

The gdbserver module implements the remote protocoll as specified for GDB.

=== file system

The file system module provides the USB Mass Storage device as well as the real and faked files inside it.

== folders
The following lists all the folders and gives an overview what they contain.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions doc/dll/links.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
https://www3.physnet.uni-hamburg.de/physnet/Tru64-Unix/HTML/APS31DTE/DOCU_002.HTM

https://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html

45 changes: 23 additions & 22 deletions src/cli/cli_swd.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,23 @@ bool cmd_swd_test(uint32_t loop)
{
res = target_connect(false);
}
if (1 > res)
if(RESULT_OK == res)
{
if(0 == res)
{
// ok
step = 2;
}
else
{
// error
debug_line("ERROR: SWD: failed to connect (%ld)!", res);
return true;
}
// ok
step = 2;
return false;
}
else if(ERR_NOT_COMPLETED == res)
{
// call again
return false;
}
else
{
// error
debug_line("ERROR: SWD: failed to connect (%ld)!", res);
return true;
}
// else busy -> call again
return false;
}
else if(2 == step)
{
Expand All @@ -75,7 +76,7 @@ bool cmd_swd_test(uint32_t loop)
res = swd_scan();
if (1 > res)
{
if(0 == res)
if(RESULT_OK == res)
{
// ok -> done
return true;
Expand Down Expand Up @@ -111,19 +112,19 @@ bool cmd_swd_connect(uint32_t loop)
{
res = target_connect(false);
}
if(0 == res)
if(RESULT_OK == res)
{
return true;
}
else if(0 > res)
else if(ERR_NOT_COMPLETED == res)
{
debug_line("ERROR: SWD: failed to connect (%ld)!", res);
return true;
// not yet complete
return false;
}
else
{
// not yet complete
return false;
debug_line("ERROR: SWD: failed to connect (%ld)!", res);
return true;
}
}

Expand Down Expand Up @@ -165,7 +166,7 @@ bool cmd_swd_ap_read(uint32_t loop)
uint32_t data = 0;

res = target_read_result(progress, &data);
if(ERR_NOT_YET_AVAILABLE == res)
if(ERR_NOT_COMPLETED == res)
{
// not yet complete
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/file/target_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Result target_read_result(Result transaction, uint32_t* data)
Result target_connect(bool first_call)
{
(void) first_call;
return swd_connect(false, 0);
return ERR_WRONG_STATE;
}

bool target_is_connected(void)
Expand Down
3 changes: 1 addition & 2 deletions src/probe_api/result.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@
#define ERR_QUEUE_FULL_TRY_AGAIN -1
#define ERR_WRONG_STATE -2
#define ERR_NOT_CONNECTED -3
#define ERR_NOT_YET_AVAILABLE -4
#define ERR_NOT_COMPLETED -4
#define ERR_INVALID_TRANSACTION_ID -5
#define ERR_TIMEOUT -6
#define ERR_TARGET_ERROR -7
#define ERR_INVALID_QUEUE -8
#define ERR_NOT_COMPLETED -9


typedef int32_t Result;
Expand Down
54 changes: 54 additions & 0 deletions src/probe_api/swd.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,67 @@
#include <stdbool.h>
#include "result.h"

#ifdef FEAT_DEBUG_UART
/** prints all available information on the debug UART.
*
* @param which the information to report. (counting up until this returns true)
* @return true = everything printed; false = more information available.
*/
bool swd_info(uint32_t which);
#endif

// configuration
/** set the value of APSEL.
* There could be more than one (Memory) Access Port. Therefore the address of the AP to use needs to be set.
* The available APs can be scanned.
* @param val the value of APSEL to use. (in most cases probably =0)
*/
void swd_protocol_set_AP_sel(uint32_t val);

// SWD actions:
/** open a connection to the target chip.
*
* @param multi false = SWDv1; true = SWDv2 (multi drop system)
* @param target value to be used on TARGETSEL command to DP.
* @return ERR_QUEUE_FULL_TRY_AGAIN or a transaction id.
*/
Result swd_connect(bool multi, uint32_t target);

/** is the connection to the target chip established?
*
* @return true = connection to target chip is open; false = no SWD communication happening.
*/
bool swd_is_connected(void);

/** scan the SWD Interface of the target chip.
* This tries to read all available information about the chip.
* This can be helpful when trying t get a new chip supported.
*
* @return ERR_QUEUE_FULL_TRY_AGAIN or RESULT_OK
*/
Result swd_scan(void);

/** read a certain memory position from the target chip memory.
*
* @param addr the address in the targets address space.
* @return ERR_QUEUE_FULL_TRY_AGAIN or a transaction id.
*/
Result swd_read_ap(uint32_t addr);

/** write somthing into the target chip memory.
*
* @param addr address in target chip memory area.
* @param data the data to write
* @return ERR_QUEUE_FULL_TRY_AGAIN or RESULT_OK
*/
Result swd_write_ap(uint32_t addr, uint32_t data);

/** try to receive some data.
* If one received a transaction id from another function then the result of that function _must_ be read (to free the queue).
* @param transaction the transaction id
* @param data where to write the received data
* @return ERR_INVALID_TRANSACTION_ID, ERR_WRONG_STATE, ERR_NOT_COMPLETED or RESULT_OK
*/
Result swd_get_result(Result transaction, uint32_t* data);

#endif /* PROBE_API_SWD_H_ */
2 changes: 1 addition & 1 deletion src/swd/result_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Result result_queue_get_result(result_queue_typ queue_id, Result transaction, ui
}
else
{
return ERR_NOT_YET_AVAILABLE;
return ERR_NOT_COMPLETED;
}
}
else
Expand Down
2 changes: 1 addition & 1 deletion src/swd/result_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Result result_queue_add_result_of(result_queue_typ queue_id, uint32_t transactio
* @param queue_id command or Packet queue
* @param transaction id of the transaction. (range 1..MAX_QUEUE_ENTRIES)
* @param data [OUT] result value of the transaction.
* @return ERR_INVALID_TRANSACTION_ID, ERR_WRONG_STATE, ERR_NOT_YET_AVAILABLE or RESULT_OK
* @return ERR_INVALID_TRANSACTION_ID, ERR_WRONG_STATE, ERR_NOT_COMPLETED or RESULT_OK
*/
Result result_queue_get_result(result_queue_typ queue_id, Result transaction, uint32_t* data);

Expand Down
59 changes: 51 additions & 8 deletions src/swd/swd_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ static const order_handler order_look_up[NUM_ORDERS] = {
connect_handler,
scan_handler,
read_handler,
write_handler,
};

#ifdef FEAT_DEBUG_UART
static const char* order_names[NUM_ORDERS] = {
"connect",
"scan",
"read",
"write",
};
#endif

Expand All @@ -58,12 +60,13 @@ void swd_init(void)

void swd_tick(void)
{
swd_packets_tick();
// handle commands
handle_order();

// handle things that need to be done regularly / independent of any commands
swd_packets_tick();
swd_protocol_tick();
swd_packets_tick();
}

Result swd_connect(bool multi, uint32_t target)
Expand All @@ -76,11 +79,21 @@ Result swd_connect(bool multi, uint32_t target)
}
if(cmdq_read != next_idx)
{
cmd_queue[cmdq_write].order = CMD_CONNECT;
cmd_queue[cmdq_write].flag = multi;
cmd_queue[cmdq_write].i_val = target;
cmdq_write = next_idx;
return 0;
uint32_t tid;
Result res = result_queue_get_next_transaction_id(COMMAND_QUEUE, &tid);
if(RESULT_OK == res)
{
cmd_queue[cmdq_write].order = CMD_CONNECT;
cmd_queue[cmdq_write].flag = multi;
cmd_queue[cmdq_write].i_val = target;
cmd_queue[cmdq_write].transaction_id = tid;
cmdq_write = next_idx;
return (Result)tid;
}
else
{
return res;
}
}
else
{
Expand All @@ -100,7 +113,29 @@ Result swd_scan(void)
{
cmd_queue[cmdq_write].order = CMD_SCAN;
cmdq_write = next_idx;
return 0;
return RESULT_OK;
}
else
{
return ERR_QUEUE_FULL_TRY_AGAIN;
}
}

Result swd_write_ap(uint32_t addr, uint32_t data)
{
// TODO protect against concurrent access (cmdq_write)
uint32_t next_idx = cmdq_write + 1;
if(CMD_QUEUE_LENGTH == next_idx)
{
next_idx = 0;
}
if(cmdq_read != next_idx)
{
cmd_queue[cmdq_write].order = CMD_WRITE;
cmd_queue[cmdq_write].address = addr;
cmd_queue[cmdq_write].i_val = data;
cmdq_write = next_idx;
return RESULT_OK;
}
else
{
Expand All @@ -123,7 +158,7 @@ Result swd_read_ap(uint32_t addr)
if(RESULT_OK == res)
{
cmd_queue[cmdq_write].order = CMD_READ;
cmd_queue[cmdq_write].i_val = addr;
cmd_queue[cmdq_write].address = addr;
cmd_queue[cmdq_write].transaction_id = tid;
cmdq_write = next_idx;
return (Result)tid;
Expand Down Expand Up @@ -180,6 +215,10 @@ static void handle_order(void)
{
// error
debug_line("swd: error %ld on order %s", order_state, order_names[cmd_queue[cmdq_read].order]);
if(CMD_CONNECT == cmd_queue[cmdq_read].order)
{
result_queue_add_result_of(COMMAND_QUEUE, cmd_queue[cmdq_read].transaction_id, (uint32_t)ERR_TARGET_ERROR);
}
}
else
{
Expand Down Expand Up @@ -208,6 +247,10 @@ static void handle_order(void)
debug_line("ERROR: SWD: timeout in running %s order !", order_names[cmd_queue[cmdq_read].order]);
timeout_counter = 0;
// TODO can we do something better than to just skip this command?
if(CMD_CONNECT == cmd_queue[cmdq_read].order)
{
result_queue_add_result_of(COMMAND_QUEUE, cmd_queue[cmdq_read].transaction_id, (uint32_t)ERR_TIMEOUT);
}
// do not try anymore
cur_order = NULL;
cmdq_read++;
Expand Down
2 changes: 2 additions & 0 deletions src/swd/swd_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ typedef enum {
CMD_CONNECT = 0,
CMD_SCAN,
CMD_READ,
CMD_WRITE,
// new orders go here
NUM_ORDERS, // <- do not use other than array size !
}order_typ;

typedef struct{
order_typ order;
bool flag;
uint32_t address;
uint32_t i_val;
uint32_t transaction_id;
} command_typ;
Expand Down
2 changes: 1 addition & 1 deletion src/swd/swd_packets.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ Result swd_packet_read(uint32_t APnotDP, uint32_t address);
*
* @param transaction transaction id as returned by @swd_packet_read()
* @param data [OUT] the bits read
* @return ERR_INVALID_TRANSACTION_ID, ERR_NOT_YET_AVAILABLE, ERR_WRONG_STATE or RESULT_OK
* @return ERR_INVALID_TRANSACTION_ID, ERR_NOT_COMPLETED, ERR_WRONG_STATE or RESULT_OK
*/
Result swd_packet_get_result(Result transaction, uint32_t* data);

Expand Down
Loading

0 comments on commit 221bc97

Please sign in to comment.