C2A_Core
memory_dump.c
[詳解]
1 #pragma section REPRO
2 #include "memory_dump.h"
3 
4 #include <string.h> // for memcpy
5 
6 #include "../System/TimeManager/time_manager.h"
7 #include "../TlmCmd/packet_handler.h"
8 #include "../Library/endian.h"
9 #include "../TlmCmd/common_cmd_packet_util.h"
10 
13 
14 // FIXME: CTCP 大改修が終わったら直す
15 // https://github.com/ut-issl/c2a-core/pull/217
16 #if 0
17 static CommonTlmPacket MEM_ctp_; // データサイズが大きいのでstatic確保
18 #endif
19 
20 static void MEM_init_(void);
21 
22 static uint8_t MEM_get_next_adu_counter_(void);
23 
24 // FIXME: CTCP 大改修が終わったら直す
25 // https://github.com/ut-issl/c2a-core/pull/217
26 #if 0
27 static CCP_EXEC_STS MEM_dump_region_(uint8_t category,
28  uint8_t num_dumps);
29 
30 static MEM_ACK MEM_form_packet_(TCP* packet,
31  uint8_t category);
32 
33 static TCP_SEQ_FLAG MEM_judge_seq_flag_(uint32_t rp,
34  size_t len);
35 
36 static void MEM_setup_header_(TCP* packet,
37  size_t data_len,
38  uint8_t category,
39  uint8_t adu_cnt,
40  TCP_SEQ_FLAG adu_seq_flag,
41  uint16_t adu_seq_cnt,
42  uint32_t adu_len);
43 
44 static void MEM_send_packet_(const CommonTlmPacket* packet,
45  uint8_t num_dumps);
46 #endif
47 
49 {
50  return AI_create_app_info("mem", MEM_init_, NULL);
51 }
52 
53 static void MEM_init_(void)
54 {
55  memory_dump_.begin = 0;
56  memory_dump_.end = 0;
60 }
61 
63 {
64  const uint8_t* param = CCP_get_param_head(packet);
65  uint32_t begin, end, span;
66 
67  // パラメータを読み出し
68  ENDIAN_memcpy(&begin, param, 4);
69  ENDIAN_memcpy(&end, param + 4, 4);
70 
71  if (begin > end)
72  {
73  // 領域の開始と終了の大小関係が逆の場合は異常終了
75  }
76 
77  span = end - begin;
78 
79  if (span > MEM_MAX_SPAN)
80  {
81  // 指定ダンプ幅が最大量を超えている場合は異常終了。
83  }
84 
85  memory_dump_.begin = begin;
86  memory_dump_.end = end;
87  memory_dump_.adu_size = span;
89 
90  // 領域設定1回毎に独立したADUカウント値を割り当てる。
92 
94 }
95 
96 // FIXME: CTCP 大改修が終わったら直す
97 // https://github.com/ut-issl/c2a-core/pull/217
98 #if 0
99 CCP_CmdRet Cmd_MEM_DUMP_REGION_SEQ(const CommonCmdPacket* packet)
100 {
101  const uint8_t* param = CCP_get_param_head(packet);
102  uint8_t category, num_dumps;
103 
104  // パラメータを読み出し
105  category = param[0];
106  num_dumps = param[1];
107 
108  if (num_dumps >= 8)
109  {
110  // パケット生成回数の上限は8回とする。
111  // 32kbpsでのDL時に8VCDU/secで1秒分の通信量。
112  // これを超える場合は複数回コマンドを送信して対応する。
114  }
115 
116  return MEM_dump_region_(category, num_dumps);
117 }
118 
119 CCP_CmdRet Cmd_MEM_DUMP_REGION_RND(const CommonCmdPacket* packet)
120 {
121  const uint8_t* param = CCP_get_param_head(packet);
122  uint8_t category, num_dumps;
123  uint16_t adu_seq;
124  uint32_t rp;
125 
126  // パラメータを読み出し
127  category = param[0];
128  num_dumps = param[1];
129 
130  if (num_dumps >= 8)
131  {
132  // パケット生成回数の上限は8回とする。
133  // 32kbpsでのDL時に8VCDU/secで1秒分の通信量。
134  // これを超える場合は複数回コマンドを送信して対応する。
136  }
137 
138  ENDIAN_memcpy(&adu_seq, param + 2, 2);
139 
140  rp = memory_dump_.begin + (adu_seq * MEM_DUMP_WIDTH);
141 
142  if (rp < memory_dump_.end)
143  {
144  // 指定されたADU Sequence Counterが領域内なら値を取り込み、
145  // 指定された位置の内容をダンプ。
146  // 「指定する = ダンプしたい」と判断している
147  memory_dump_.adu_seq = adu_seq;
148  return MEM_dump_region_(category, num_dumps);
149  }
150  else
151  {
152  // 指定されたADU Sequence Counterが領域外であれば異常終了
154  }
155 }
156 
157 CCP_CmdRet Cmd_MEM_DUMP_SINGLE(const CommonCmdPacket* packet)
158 {
159  const uint8_t* param = CCP_get_param_head(packet);
160  uint8_t category, num_dumps;
161  uint32_t start_addr;
162  uint8_t* data;
163 
164  // パラメータを読み出し
165  category = param[0];
166  num_dumps = param[1];
167 
168  if (num_dumps >= 8)
169  {
170  // パケット生成回数の上限は8回とする。
171  // 32kbpsでのDL時に8VCDU/secで1秒分の通信量。
172  // これを超える場合は複数回コマンドを送信して対応する。
174  }
175 
176  ENDIAN_memcpy(&start_addr, param + 2, 4);
177 
178  // 要検討: 指定アドレス値が異常な場合の処理をすべきか?
179  // Segmentation Faultとか起こる?
180 
181  // メモリダンプパケットのヘッダを設定
182  // Packet Sequence Counter for each ADUは単パケットなので0固定。
183  // ADU分割形式にしなければ5Bytes分ダンプ領域を増やせるが、
184  // Packet IDも別にする必要が生じるのでひとまず形式を合わせて実装する。
185  MEM_setup_header_(&MEM_ctp_,
186  MEM_DUMP_WIDTH, // 1パケットの最大長をダンプする
187  category, // 送出カテゴリはパラメータで指定
188  MEM_get_next_adu_counter_(), // 単ADUなのでADUカウント値を直接割り当て
189  TCP_SEQ_SINGLE, // アドレス指定の場合は単ADUとして処理
190  0x0000, // 単ADUなので0x0000に固定
191  MEM_DUMP_WIDTH); // ADU長はDUMP長と同一
192 
193  // ダンプデータを設定
194  // FIXME: CTCP, SpacePacket 整理で直す. TCP依存性もやめる
195  data = TCP_TLM_get_user_data_head(&MEM_ctp_) + 5; // ADU分割によりヘッダ長が5Bytes増える
196  memcpy(data, (const void*)start_addr, MEM_DUMP_WIDTH);
197 
198  // 生成したパケットを送出
199  MEM_send_packet_(&MEM_ctp_, num_dumps);
200 
202 }
203 #endif
204 
206 {
207  const uint8_t* param = CCP_get_param_head(packet);
208  size_t param_len = CCP_get_param_len(packet);
209  size_t data_len;
210  uint32_t start_addr;
211 
212  // データ長読み出し
213  // データ長 -> パラメータ全長-開始アドレスパラメータ長
214  data_len = param_len - 4;
215 
216  // 書き込みアドレス読み出し
217  ENDIAN_memcpy(&start_addr, param, 4);
218 
219  // 指定した開始アドレスから始まる領域にデータを書き込み
220  memcpy((void*)start_addr, &(param[4]), data_len);
222 }
223 
225 {
226  const uint8_t* param = CCP_get_param_head(packet);
227  uint32_t dest;
228 
229  ENDIAN_memcpy(&dest, param, 4);
230 
231  if ((dest >= memory_dump_.begin) && (dest < memory_dump_.end))
232  {
233  // 宛先アドレスが領域内部に含まれる場合。
234  // これを認めると処理が複雑になるので禁止する。
236  }
237 
238  // 宛先アドレスを設定し、RPを領域先頭に合わせる。
239  memory_dump_.dest = dest;
242 }
243 
245 {
246  const uint8_t* param = CCP_get_param_head(packet);
247  uint32_t copy_width, wp;
248 
250  {
251  // 既に領域全体の読み出しが完了している場合。
252  // 処理は行わず正常終了する。
254  }
255 
256  // パラメータ読み出し。
257  ENDIAN_memcpy(&copy_width, param, 4);
258 
259  if ((memory_dump_.rp + copy_width) > memory_dump_.end)
260  {
261  // 指定コピー幅でコピーすると領域外に出てしまう場合。
262  // コピー結果が領域終端に一致するようコピー幅をクリップ。
263  copy_width = memory_dump_.end - memory_dump_.rp;
264  }
265 
266  // WP計算。WP = 宛先先頭+読み出し済みデータ量。
268 
269  // 指定されたコピー幅だけ領域をコピーし、RPを更新。
270  memcpy((uint8_t*)wp, (const uint8_t*)memory_dump_.rp, copy_width);
271  memory_dump_.rp += copy_width;
273 }
274 
275 static uint8_t MEM_get_next_adu_counter_(void)
276 {
277  // インクリメント後の値を返すので初期値は0xffとする。
278  static uint8_t adu_counter_ = 0xff;
279  return ++adu_counter_;
280 }
281 
282 // FIXME: CTCP 大改修が終わったら直す
283 // https://github.com/ut-issl/c2a-core/pull/217
284 #if 0
285 static CCP_EXEC_STS MEM_dump_region_(uint8_t category,
286  uint8_t num_dumps)
287 {
288  MEM_ACK ack;
289 
290  // 設定値にもとづき送出すべきパケットを構築
291  ack = MEM_form_packet_(&MEM_ctp_, category);
292 
293  switch (ack)
294  {
295  case MEM_SUCCESS:
296  // 生成したパケットを送出し、ADU Sequence Counterの値を更新
297  MEM_send_packet_(&MEM_ctp_, num_dumps);
300 
301  case MEM_NO_DATA:
302  // すでに全領域ダンプ済みなら何もせず終了
304 
305  default:
306  // それ以外のエラーはないはず
308  }
309 }
310 
311 static MEM_ACK MEM_form_packet_(TCP* packet,
312  uint8_t category)
313 {
314  uint32_t rp;
315  size_t len;
316  TCP_SEQ_FLAG seq_flag;
317  uint8_t* data;
318 
320 
321  if (rp >= memory_dump_.end)
322  {
323  // Read Pointerが終端に達していれば何もせず終了
324  return MEM_NO_DATA;
325  }
326 
327  // 残りダンプ長を計算
328  len = memory_dump_.end - rp;
329 
330  if (len > MEM_DUMP_WIDTH)
331  {
332  // 1パケットのダンプ幅を超える場合はダンプ幅に押さえる。
333  len = MEM_DUMP_WIDTH;
334  }
335 
336  // Packet Sequence Flagの種別判定
337  seq_flag = MEM_judge_seq_flag_(rp, len);
338 
339  // メモリダンプパケットのヘッダを設定
340  MEM_setup_header_(&MEM_ctp_,
341  len,
342  category,
344  seq_flag,
347 
348  // ダンプデータを設定
349  data = TCP_TLM_get_user_data_head(packet) + 5; // ADU分割によりヘッダ長が5Bytes増える
350  memcpy(data, (const void*)rp, len);
351 
352  return MEM_SUCCESS;
353 }
354 
355 static TCP_SEQ_FLAG MEM_judge_seq_flag_(uint32_t rp,
356  size_t len)
357 {
359  {
360  // ADUが単パケットに収まる場合
361  return TCP_SEQ_SINGLE;
362  }
363  else
364  {
365  // ADUが複数パケットにまたがる場合
366  if (rp == memory_dump_.begin)
367  {
368  // Read Pointerが読み出し領域先頭に一致するなら開始パケット
369  return TCP_SEQ_FIRST;
370  }
371  else if (len < MEM_DUMP_WIDTH)
372  {
373  // ダンプ残量が1パケット以内に収まるなら終了パケット
374  return TCP_SEQ_LAST;
375  }
376  else
377  {
378  // それ以外の場合は中間パケット
379  return TCP_SEQ_CONT;
380  }
381  }
382 }
383 
384 static void MEM_setup_header_(TCP* packet,
385  size_t data_len,
386  uint8_t category,
387  uint8_t adu_cnt,
388  TCP_SEQ_FLAG adu_seq_flag,
389  uint16_t adu_seq_cnt,
390  uint32_t adu_len)
391 {
392  uint8_t* data;
393 
394  // TCPacketヘッダを設定
395  TCP_TLM_setup_primary_hdr(packet, APID_DUMP_TLM, (uint16_t)(data_len + 12));
396  TCP_TLM_set_ti(packet, (uint32_t)( TMGR_get_master_total_cycle() ));
397  TCP_TLM_set_category(packet, category); // パラメータによる指定
398  TCP_TLM_set_packet_id(packet, (uint8_t)MEM_TLM_ID);
399  TCP_TLM_set_adu_cnt(packet, adu_cnt);
400  TCP_TLM_set_adu_seq_flag(packet, adu_seq_flag);
401 
402  // ADU分割時のSecondary Header追加分を設定
403  data = TCP_TLM_get_user_data_head(packet);
404  data[0] = (uint8_t)(adu_seq_cnt >> 8);
405  data[1] = (uint8_t)(adu_seq_cnt);
406  data += 2;
407  // ADU Lengthを設定 3Bytes長なので注意
408  data[0] = (uint8_t)(adu_len >> 16);
409  data[1] = (uint8_t)(adu_len >> 8);
410  data[2] = (uint8_t)(adu_len);
411 }
412 
413 static void MEM_send_packet_(const CommonTlmPacket* packet,
414  uint8_t num_dumps)
415 {
416  int i;
417 
418  // TLM送出処理
419  for (i = 0; i < num_dumps; ++i)
420  {
421  // num_dumpsの回数だけ生成したパケットを配送処理へ渡す
422  PH_analyze_packet(packet); // FIXME: CTCP, SpacePacket 整理で直す
423  }
424 }
425 #endif
426 
427 #pragma section
@ APID_DUMP_TLM
11100010000b: APID for DUMP TLM (FIXME: 現在まともに使ってない)
Definition: apid_define.h:25
AppInfo AI_create_app_info(const char *name, void(*initializer)(void), void(*entry_point)(void))
AppInfo を作る
Definition: app_info.c:9
CCP_EXEC_STS
コマンド実行結果コード
@ CCP_EXEC_UNKNOWN
内部処理用.使わない.
@ CCP_EXEC_SUCCESS
@ CCP_EXEC_ILLEGAL_PARAMETER
コマンド実行時のパラメタエラー
@ CCP_EXEC_ILLEGAL_CONTEXT
コマンド実行時のその他のエラー
uint16_t CCP_get_param_len(const CommonCmdPacket *packet)
CMD パラメタ長を取得
const uint8_t * CCP_get_param_head(const CommonCmdPacket *packet)
先頭のパラメタのポインタを取得
CCP_CmdRet CCP_make_cmd_ret_without_err_code(CCP_EXEC_STS exec_sts)
コマンド返り値である CCP_CmdRet を作成(エラーコード不使用版)
void * ENDIAN_memcpy(void *dest, const void *src, size_t size)
エンディアンを考慮した memcpy
Definition: endian.c:11
CCP_CmdRet Cmd_MEM_SET_REGION(const CommonCmdPacket *packet)
Definition: memory_dump.c:62
CCP_CmdRet Cmd_MEM_COPY_REGION_SEQ(const CommonCmdPacket *packet)
Definition: memory_dump.c:244
CCP_CmdRet Cmd_MEM_LOAD(const CommonCmdPacket *packet)
Definition: memory_dump.c:205
const MemoryDump *const memory_dump
Definition: memory_dump.c:12
AppInfo MEM_create_app(void)
Definition: memory_dump.c:48
static uint8_t MEM_get_next_adu_counter_(void)
Definition: memory_dump.c:275
CCP_CmdRet Cmd_MEM_SET_DESTINATION(const CommonCmdPacket *packet)
Definition: memory_dump.c:224
static void MEM_init_(void)
Definition: memory_dump.c:53
static MemoryDump memory_dump_
Definition: memory_dump.c:11
#define MEM_DUMP_WIDTH
Definition: memory_dump.h:8
MEM_ACK
Definition: memory_dump.h:12
@ MEM_NO_DATA
Definition: memory_dump.h:14
@ MEM_SUCCESS
Definition: memory_dump.h:13
#define MEM_TLM_ID
Definition: memory_dump.h:7
#define MEM_MAX_SPAN
Definition: memory_dump.h:9
PH_ACK PH_analyze_packet(const CommonTlmCmdPacket *packet)
CTCP を解析する
コマンド返り値
Space Packet (コマンド用)
uint32_t rp
Definition: memory_dump.h:25
uint8_t adu_counter
Definition: memory_dump.h:23
uint16_t adu_seq
Definition: memory_dump.h:22
uint32_t end
Definition: memory_dump.h:20
uint32_t begin
Definition: memory_dump.h:19
uint32_t adu_size
Definition: memory_dump.h:21
uint32_t dest
Definition: memory_dump.h:24
Space Packet (テレメ用)
cycle_t TMGR_get_master_total_cycle(void)
現在の total_cycle を返す
Definition: time_manager.c:97