Автоматическая прошивка Zynq и запуск приемника — различия между версиями
Korogodin (обсуждение | вклад) (→Автоматическая прошивка ПЛИС) |
Dneprov D (обсуждение | вклад) |
||
| (не показаны 10 промежуточных версий 1 участника) | |||
| Строка 49: | Строка 49: | ||
== receiver аки демон == | == receiver аки демон == | ||
| − | Аналогично пишем скрипт для запуска receiver: | + | Аналогично пишем скрипт для запуска receiver (слизано со скрипта демона rsync): |
| − | <source lang="bash"> | + | |
| + | {{Hider | ||
| + | |title = Содержимое /etc/init.d/receiver | ||
| + | |content = <source lang="bash"> | ||
#!/bin/bash | #!/bin/bash | ||
### BEGIN INIT INFO | ### BEGIN INIT INFO | ||
# Provides: receiver | # Provides: receiver | ||
| − | # Required-Start: burnedzynq $local_fs $remote_fs | + | # Required-Start: burnedzynq $all $local_fs $remote_fs |
# Required-Stop: $local_fs $remote_fs | # Required-Stop: $local_fs $remote_fs | ||
# Should-Start: | # Should-Start: | ||
| Строка 63: | Строка 66: | ||
### END INIT INFO | ### END INIT INFO | ||
| − | /tmp/receiver | + | set -e |
| + | |||
| + | # /etc/init.d/receiver: start and stop the receiver daemon | ||
| + | |||
| + | DAEMON=/tmp/receiver | ||
| + | REC_ENABLE=true | ||
| + | REC_OPTS='' | ||
| + | REC_DEFAULTS_FILE=/etc/default/receiver | ||
| + | REC_CONFIG_FILE=/etc/receiver.conf | ||
| + | REC_PID_FILE=/var/run/receiver.pid | ||
| + | REC_NICE_PARM='' | ||
| + | REC_IONICE_PARM='' | ||
| + | |||
| + | test -x $DAEMON || exit 0 | ||
| + | |||
| + | . /lib/lsb/init-functions | ||
| + | |||
| + | if [ -s $REC_DEFAULTS_FILE ]; then | ||
| + | . $REC_DEFAULTS_FILE | ||
| + | case "x$REC_ENABLE" in | ||
| + | xtrue|xfalse) ;; | ||
| + | xinetd) exit 0 | ||
| + | ;; | ||
| + | *) log_failure_msg "Value of REC_ENABLE in $REC_DEFAULTS_FILE must be either 'true' or 'false';" | ||
| + | log_failure_msg "not starting receiver daemon." | ||
| + | exit 1 | ||
| + | ;; | ||
| + | esac | ||
| + | case "x$REC_NICE" in | ||
| + | x[0-9]) REC_NICE_PARM="--nicelevel $REC_NICE";; | ||
| + | x1[0-9]) REC_NICE_PARM="--nicelevel $REC_NICE";; | ||
| + | x) ;; | ||
| + | *) log_warning_msg "Value of REC_NICE in $REC_DEFAULTS_FILE must be a value between 0 and 19 (inclusive);" | ||
| + | log_warning_msg "ignoring REC_NICE now." | ||
| + | ;; | ||
| + | esac | ||
| + | case "x$REC_IONICE" in | ||
| + | x-c[123]*) REC_IONICE_PARM="$REC_IONICE";; | ||
| + | x) ;; | ||
| + | *) log_warning_msg "Value of REC_IONICE in $REC_DEFAULTS_FILE must be -c1, -c2 or -c3;" | ||
| + | log_warning_msg "ignoring REC_IONICE now." | ||
| + | ;; | ||
| + | esac | ||
| + | fi | ||
| + | |||
| + | export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" | ||
| + | |||
| + | receiver_start() { | ||
| + | if [ ! -s "$REC_CONFIG_FILE" ]; then | ||
| + | log_failure_msg "missing or empty config file $REC_CONFIG_FILE" | ||
| + | log_end_msg 1 | ||
| + | exit 0 | ||
| + | fi | ||
| + | # See ionice(1) | ||
| + | if [ -n "$REC_IONICE_PARM" ] && [ -x /usr/bin/ionice ] && | ||
| + | /usr/bin/ionice "$REC_IONICE_PARM" true 2>/dev/null; then | ||
| + | /usr/bin/ionice "$REC_IONICE_PARM" -p$$ > /dev/null 2>&1 | ||
| + | fi | ||
| + | if start-stop-daemon --start --quiet --background \ | ||
| + | --pidfile $REC_PID_FILE --make-pidfile \ | ||
| + | $REC_NICE_PARM --exec $DAEMON \ | ||
| + | -- --no-detach --daemon --config "$REC_CONFIG_FILE" $REC_OPTS | ||
| + | then | ||
| + | rc=0 | ||
| + | sleep 1 | ||
| + | if ! kill -0 $(cat $REC_PID_FILE) >/dev/null 2>&1; then | ||
| + | log_failure_msg "receiver daemon failed to start" | ||
| + | rc=1 | ||
| + | fi | ||
| + | else | ||
| + | rc=1 | ||
| + | fi | ||
| + | if [ $rc -eq 0 ]; then | ||
| + | log_end_msg 0 | ||
| + | else | ||
| + | log_end_msg 1 | ||
| + | rm -f $REC_PID_FILE | ||
| + | fi | ||
| + | } # receiver_start | ||
| + | |||
| + | |||
| + | case "$1" in | ||
| + | start) | ||
| + | if "$REC_ENABLE"; then | ||
| + | log_daemon_msg "Starting receiver daemon" "receiver" | ||
| + | if [ -s $REC_PID_FILE ] && kill -0 $(cat $REC_PID_FILE) >/dev/null 2>&1; then | ||
| + | log_progress_msg "apparently already running" | ||
| + | log_end_msg 0 | ||
| + | exit 0 | ||
| + | fi | ||
| + | receiver_start | ||
| + | else | ||
| + | if [ -s "$REC_CONFIG_FILE" ]; then | ||
| + | [ "$VERBOSE" != no ] && log_warning_msg "receiver daemon not enabled in $REC_DEFAULTS_FILE, not starting..." | ||
| + | fi | ||
| + | fi | ||
| + | ;; | ||
| + | stop) | ||
| + | log_daemon_msg "Stopping receiver daemon" "receiver" | ||
| + | start-stop-daemon --stop --quiet --oknodo --pidfile $REC_PID_FILE | ||
| + | log_end_msg $? | ||
| + | rm -f $REC_PID_FILE | ||
| + | ;; | ||
| + | |||
| + | reload|force-reload) | ||
| + | log_warning_msg "Reloading receiver daemon: not needed, as the daemon" | ||
| + | log_warning_msg "re-reads the config file whenever a client connects." | ||
| + | ;; | ||
| + | |||
| + | restart) | ||
| + | set +e | ||
| + | if $REC_ENABLE; then | ||
| + | log_daemon_msg "Restarting receiver daemon" "receiver" | ||
| + | if [ -s $REC_PID_FILE ] && kill -0 $(cat $REC_PID_FILE) >/dev/null 2>&1; then | ||
| + | start-stop-daemon --stop --quiet --oknodo --pidfile $REC_PID_FILE || true | ||
| + | sleep 1 | ||
| + | else | ||
| + | log_warning_msg "receiver daemon not running, attempting to start." | ||
| + | rm -f $REC_PID_FILE | ||
| + | fi | ||
| + | receiver_start | ||
| + | else | ||
| + | if [ -s "$REC_CONFIG_FILE" ]; then | ||
| + | [ "$VERBOSE" != no ] && log_warning_msg "receiver daemon not enabled in $REC_DEFAULTS_FILE, not starting..." | ||
| + | fi | ||
| + | fi | ||
| + | ;; | ||
| + | |||
| + | status) | ||
| + | status_of_proc -p $REC_PID_FILE "$DAEMON" receiver | ||
| + | exit $? # notreached due to set -e | ||
| + | ;; | ||
| + | *) | ||
| + | echo "Usage: /etc/init.d/receiver {start|stop|reload|force-reload|restart|status}" | ||
| + | exit 1 | ||
| + | esac | ||
| + | |||
| + | exit 0 | ||
</source> | </source> | ||
| + | |frame-style = border:1px solid Plum | ||
| + | |title-style = color:black;background-color:lavender;font-weight:bold | ||
| + | |content-style = color:black;background-color:ghostwhite;text-align:left | ||
| + | |footer = | ||
| + | |footer-style = background-color:lightgray;text-align:right | ||
| + | |hidden = | ||
| + | }} | ||
Делаем исполняемым: | Делаем исполняемым: | ||
<source lang="bash">chmod +x receiver</source> | <source lang="bash">chmod +x receiver</source> | ||
| + | |||
| + | Создаем конфигурационный файл (пока не используется): | ||
| + | <source lang="bash">echo '#GNSS Receiver configuration file' > /etc/receiver.conf</source> | ||
Создаем ссылки: | Создаем ссылки: | ||
| Строка 75: | Строка 225: | ||
Выключаем/включаем питание приемника. Убеждаемся, что приемник отсылает пакеты. | Выключаем/включаем питание приемника. Убеждаемся, что приемник отсылает пакеты. | ||
| + | |||
| + | Теперь с приемником можно работать как со службой: | ||
| + | <source lang="bash">Usage: /etc/init.d/receiver {start|stop|reload|force-reload|restart|status}</source> | ||
| + | |||
| + | Например: | ||
| + | <source lang="bash"> | ||
| + | root@plda:~# /etc/init.d/receiver status | ||
| + | [ ok ] receiver is running. | ||
| + | </source> | ||
| + | |||
| + | == В случае Импалы == | ||
| + | |||
| + | В Импале есть ряд отличий: | ||
| + | * нет некоторых скриптов SystemV; | ||
| + | * вместо bash используется sh; | ||
| + | * после перезагрузки стирается /tmp, | ||
| + | поэтому скрипт иной: | ||
| + | {{Hider | ||
| + | |title = Содержимое /etc/init.d/receiver | ||
| + | |content = <source lang="bash"> | ||
| + | #!/bin/sh | ||
| + | # | ||
| + | # | ||
| + | |||
| + | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin | ||
| + | DAEMON=/tmp/receiver | ||
| + | DAEMON_TAG=/home/root/receiver | ||
| + | NAME=receiver | ||
| + | DESC="GNSS Receiver" | ||
| + | PIDFILE=/var/run/receiver.pid | ||
| + | |||
| + | REC_EXTRA_ARGS= | ||
| + | NO_START=0 | ||
| + | |||
| + | test -x "$DAEMON_TAG" || exit 0 | ||
| + | |||
| + | test -x "$DAEMON" || cp "$DAEMON_TAG" "$DAEMON" | ||
| + | |||
| + | test ! -r /etc/default/receiver || . /etc/default/receiver | ||
| + | test "$NO_START" = "0" || exit 0 | ||
| + | test -x "$DAEMON" || exit 0 | ||
| + | test ! -h /var/service/receiver || exit 0 | ||
| + | |||
| + | readonly_rootfs=0 | ||
| + | for flag in `awk '{ if ($2 == "/") { split($4,FLAGS,",") } }; END { for (f in FLAGS) print FLAGS[f] }' </proc/mounts`; do | ||
| + | case $flag in | ||
| + | ro) | ||
| + | readonly_rootfs=1 | ||
| + | ;; | ||
| + | esac | ||
| + | done | ||
| + | |||
| + | case "$1" in | ||
| + | start) | ||
| + | echo -n "Starting $DESC: " | ||
| + | start-stop-daemon --start --quiet --background \ | ||
| + | --pidfile $PIDFILE --make-pidfile \ | ||
| + | --exec "$DAEMON" -- $KEY_ARGS \ | ||
| + | --no-detach --daemon $REC_EXTRA_ARGS | ||
| + | echo "$NAME." | ||
| + | ;; | ||
| + | stop) | ||
| + | echo -n "Stopping $DESC: " | ||
| + | start-stop-daemon -K -x "$DAEMON" -p $PIDFILE | ||
| + | echo "$NAME." | ||
| + | ;; | ||
| + | restart|force-reload) | ||
| + | echo -n "Restarting $DESC: " | ||
| + | start-stop-daemon -K -x "$DAEMON" -p $PIDFILE | ||
| + | sleep 1 | ||
| + | start-stop-daemon -S -p $PIDFILE \ | ||
| + | -x "$DAEMON" -- $KEY_ARGS \ | ||
| + | $REC_EXTRA_ARGS | ||
| + | echo "$NAME." | ||
| + | ;; | ||
| + | *) | ||
| + | N=/etc/init.d/$NAME | ||
| + | echo "Usage: $N {start|stop|restart|force-reload}" >&2 | ||
| + | exit 1 | ||
| + | ;; | ||
| + | esac | ||
| + | |||
| + | exit 0 | ||
| + | </source> | ||
| + | |frame-style = border:1px solid Plum | ||
| + | |title-style = color:black;background-color:lavender;font-weight:bold | ||
| + | |content-style = color:black;background-color:ghostwhite;text-align:left | ||
| + | |footer = | ||
| + | |footer-style = background-color:lightgray;text-align:right | ||
| + | |hidden = 1 | ||
| + | }} | ||
| + | |||
| + | Перед исполнением скрипт проверяет, есть ли /tmp/receiver. Если нет - копирует туда файл /home/root/receiver. | ||
[[Category:HOWTO]] | [[Category:HOWTO]] | ||
| + | [[Category:Oryx]] | ||
| + | [[Category:Impala]] | ||
Текущая версия на 11:57, 25 ноября 2020
Накопились претензии к степени автоматизации работы с ПНП.
Во-первых, ПЛИС'овская часть Zynq'а шьется через процессор командой типа:
Что приходится исполнять после каждой перезагрузки ящика.
Во-вторых, хотелось бы, чтобы ПНП сразу мог начать работать после подачи питания.
В-третьих, на приемной стороне приходится вручную запускать srns_parse_all, tail и матлабовские скрипты.
[править] Автоматическая прошивка ПЛИС
На ум приходит два способа автоматически прошить ПЛИС при запуске ОС: через cron и через init.d. Т.к. далее воспользуемся init для старта службы receiver, то для единообразия и ПЛИС будем шить так.
В Debian нашего модуля по умолчанию используется второй run-level. Напишем скрипт, который будет выполняться при запуске. Для этого в /etc/init.d создаем файл burnzynq:
### BEGIN INIT INFO
# Provides: burnedzynq
# Required-Start: $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Should-Start:
# Should-Stop:
# Default-Start: 2
# Default-Stop:
# Short-Description: Load .bit to Zynq
### END INIT INFO
echo Zynq burning...
cat /tmp/somz.bit > /dev/xdevcfg
Файл делаем исполняемым:
Далее добавляем ссылку на него в /etc/rc2.d специальной командой:
Здесь defaults - воспользоваться Default-Start/Default-Stop.
В результате в /etc/rc2.d получаем файл S01burnzynq -> ../init.d/burnzynq.
Если потребуется обновить ссылки на burnzynq или вообще отказаться от его использования, то выполняем:
Выключаем/включаем питание приемника. После загрузки ПЛИС готова к работе.
[править] receiver аки демон
Аналогично пишем скрипт для запуска receiver (слизано со скрипта демона rsync):
### BEGIN INIT INFO
# Provides: receiver
# Required-Start: burnedzynq $all $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Should-Start:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: GNSS receiver firmware
### END INIT INFO
set -e
# /etc/init.d/receiver: start and stop the receiver daemon
DAEMON=/tmp/receiver
REC_ENABLE=true
REC_OPTS=''
REC_DEFAULTS_FILE=/etc/default/receiver
REC_CONFIG_FILE=/etc/receiver.conf
REC_PID_FILE=/var/run/receiver.pid
REC_NICE_PARM=''
REC_IONICE_PARM=''
test -x $DAEMON || exit 0
. /lib/lsb/init-functions
if [ -s $REC_DEFAULTS_FILE ]; then
. $REC_DEFAULTS_FILE
case "x$REC_ENABLE" in
xtrue|xfalse) ;;
xinetd) exit 0
;;
*) log_failure_msg "Value of REC_ENABLE in $REC_DEFAULTS_FILE must be either 'true' or 'false';"
log_failure_msg "not starting receiver daemon."
exit 1
;;
esac
case "x$REC_NICE" in
x[0-9]) REC_NICE_PARM="--nicelevel $REC_NICE";;
x1[0-9]) REC_NICE_PARM="--nicelevel $REC_NICE";;
x) ;;
*) log_warning_msg "Value of REC_NICE in $REC_DEFAULTS_FILE must be a value between 0 and 19 (inclusive);"
log_warning_msg "ignoring REC_NICE now."
;;
esac
case "x$REC_IONICE" in
x-c[123]*) REC_IONICE_PARM="$REC_IONICE";;
x) ;;
*) log_warning_msg "Value of REC_IONICE in $REC_DEFAULTS_FILE must be -c1, -c2 or -c3;"
log_warning_msg "ignoring REC_IONICE now."
;;
esac
fi
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
receiver_start() {
if [ ! -s "$REC_CONFIG_FILE" ]; then
log_failure_msg "missing or empty config file $REC_CONFIG_FILE"
log_end_msg 1
exit 0
fi
# See ionice(1)
if [ -n "$REC_IONICE_PARM" ] && [ -x /usr/bin/ionice ] &&
/usr/bin/ionice "$REC_IONICE_PARM" true 2>/dev/null; then
/usr/bin/ionice "$REC_IONICE_PARM" -p$$ > /dev/null 2>&1
fi
if start-stop-daemon --start --quiet --background \
--pidfile $REC_PID_FILE --make-pidfile \
$REC_NICE_PARM --exec $DAEMON \
-- --no-detach --daemon --config "$REC_CONFIG_FILE" $REC_OPTS
then
rc=0
sleep 1
if ! kill -0 $(cat $REC_PID_FILE) >/dev/null 2>&1; then
log_failure_msg "receiver daemon failed to start"
rc=1
fi
else
rc=1
fi
if [ $rc -eq 0 ]; then
log_end_msg 0
else
log_end_msg 1
rm -f $REC_PID_FILE
fi
} # receiver_start
case "$1" in
start)
if "$REC_ENABLE"; then
log_daemon_msg "Starting receiver daemon" "receiver"
if [ -s $REC_PID_FILE ] && kill -0 $(cat $REC_PID_FILE) >/dev/null 2>&1; then
log_progress_msg "apparently already running"
log_end_msg 0
exit 0
fi
receiver_start
else
if [ -s "$REC_CONFIG_FILE" ]; then
[ "$VERBOSE" != no ] && log_warning_msg "receiver daemon not enabled in $REC_DEFAULTS_FILE, not starting..."
fi
fi
;;
stop)
log_daemon_msg "Stopping receiver daemon" "receiver"
start-stop-daemon --stop --quiet --oknodo --pidfile $REC_PID_FILE
log_end_msg $?
rm -f $REC_PID_FILE
;;
reload|force-reload)
log_warning_msg "Reloading receiver daemon: not needed, as the daemon"
log_warning_msg "re-reads the config file whenever a client connects."
;;
restart)
set +e
if $REC_ENABLE; then
log_daemon_msg "Restarting receiver daemon" "receiver"
if [ -s $REC_PID_FILE ] && kill -0 $(cat $REC_PID_FILE) >/dev/null 2>&1; then
start-stop-daemon --stop --quiet --oknodo --pidfile $REC_PID_FILE || true
sleep 1
else
log_warning_msg "receiver daemon not running, attempting to start."
rm -f $REC_PID_FILE
fi
receiver_start
else
if [ -s "$REC_CONFIG_FILE" ]; then
[ "$VERBOSE" != no ] && log_warning_msg "receiver daemon not enabled in $REC_DEFAULTS_FILE, not starting..."
fi
fi
;;
status)
status_of_proc -p $REC_PID_FILE "$DAEMON" receiver
exit $? # notreached due to set -e
;;
*)
echo "Usage: /etc/init.d/receiver {start|stop|reload|force-reload|restart|status}"
exit 1
esac
exit 0
Делаем исполняемым:
Создаем конфигурационный файл (пока не используется):
Создаем ссылки:
Выключаем/включаем питание приемника. Убеждаемся, что приемник отсылает пакеты.
Теперь с приемником можно работать как со службой:
Например:
[ ok ] receiver is running.
[править] В случае Импалы
В Импале есть ряд отличий:
- нет некоторых скриптов SystemV;
- вместо bash используется sh;
- после перезагрузки стирается /tmp,
поэтому скрипт иной:
#
#
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/tmp/receiver
DAEMON_TAG=/home/root/receiver
NAME=receiver
DESC="GNSS Receiver"
PIDFILE=/var/run/receiver.pid
REC_EXTRA_ARGS=
NO_START=0
test -x "$DAEMON_TAG" || exit 0
test -x "$DAEMON" || cp "$DAEMON_TAG" "$DAEMON"
test ! -r /etc/default/receiver || . /etc/default/receiver
test "$NO_START" = "0" || exit 0
test -x "$DAEMON" || exit 0
test ! -h /var/service/receiver || exit 0
readonly_rootfs=0
for flag in `awk '{ if ($2 == "/") { split($4,FLAGS,",") } }; END { for (f in FLAGS) print FLAGS[f] }' </proc/mounts`; do
case $flag in
ro)
readonly_rootfs=1
;;
esac
done
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --background \
--pidfile $PIDFILE --make-pidfile \
--exec "$DAEMON" -- $KEY_ARGS \
--no-detach --daemon $REC_EXTRA_ARGS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon -K -x "$DAEMON" -p $PIDFILE
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
start-stop-daemon -K -x "$DAEMON" -p $PIDFILE
sleep 1
start-stop-daemon -S -p $PIDFILE \
-x "$DAEMON" -- $KEY_ARGS \
$REC_EXTRA_ARGS
echo "$NAME."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
Перед исполнением скрипт проверяет, есть ли /tmp/receiver. Если нет - копирует туда файл /home/root/receiver.