Преглед изворни кода

重新新增ymodem模块, 用c语言实现, 编程中...

niujiuru пре 1 недеља
родитељ
комит
b47d5ef2e0
9 измењених фајлова са 210 додато и 0 уклоњено
  1. 0 0
      ymodem/Makefile
  2. 6 0
      ymodem/bridge.go
  3. 105 0
      ymodem/ring_buf.c
  4. 97 0
      ymodem/ring_buf.h
  5. 0 0
      ymodem/ymodem.c
  6. 1 0
      ymodem/ymodem.go
  7. 0 0
      ymodem/ymodem.h
  8. 0 0
      ymodem/ymodem_test.c
  9. 1 0
      ymodem/ymodem_test.go

+ 0 - 0
ymodem/Makefile


+ 6 - 0
ymodem/bridge.go

@@ -0,0 +1,6 @@
+package ymodem
+
+/*
+#include "ymodem.h"
+*/
+import "C"

+ 105 - 0
ymodem/ring_buf.c

@@ -0,0 +1,105 @@
+//============================================================================
+// Lock-Free Ring Buffer (LFRB) for embedded systems
+// GitHub: https://github.com/QuantumLeaps/lock-free-ring-buffer
+//
+//                    Q u a n t u m  L e a P s
+//                    ------------------------
+//                    Modern Embedded Software
+//
+// Copyright (C) 2005 Quantum Leaps, <state-machine.com>.
+//
+// SPDX-License-Identifier: MIT
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//============================================================================
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "ring_buf.h"
+
+//............................................................................
+void RingBuf_ctor(RingBuf * const me,
+                  RingBufElement sto[], RingBufCtr sto_len) {
+    me->buf  = &sto[0];
+    me->end  = sto_len;
+    atomic_store(&me->head, 0U);  // initialize head atomically
+    atomic_store(&me->tail, 0U);  // initialize tail atomically
+}
+//............................................................................
+bool RingBuf_put(RingBuf * const me, RingBufElement const el) {
+    RingBufCtr head =
+        atomic_load_explicit(&me->head, memory_order_relaxed) + 1U;
+    if (head == me->end) {
+        head = 0U;
+    }
+    RingBufCtr tail = atomic_load_explicit(&me->tail, memory_order_acquire);
+    if (head != tail) { // buffer NOT full?
+        me->buf[atomic_load_explicit(&me->head, memory_order_relaxed)] = el;
+        atomic_store_explicit(&me->head, head, memory_order_release);
+        return true;
+    }
+    else {
+        return false; // buffer full
+    }
+}
+//............................................................................
+bool RingBuf_get(RingBuf * const me, RingBufElement *pel) {
+    RingBufCtr tail = atomic_load_explicit(&me->tail, memory_order_relaxed);
+    RingBufCtr head = atomic_load_explicit(&me->head, memory_order_acquire);
+    if (head != tail) { // buffer NOT empty?
+        *pel = me->buf[tail];
+        ++tail;
+        if (tail == me->end) {
+            tail = 0U;
+        }
+        atomic_store_explicit(&me->tail, tail, memory_order_release);
+        return true;
+    }
+    else {
+        return false; // buffer empty
+    }
+}
+//............................................................................
+RingBufCtr RingBuf_num_free(RingBuf * const me) {
+    RingBufCtr head = atomic_load_explicit(&me->head, memory_order_acquire);
+    RingBufCtr tail = atomic_load_explicit(&me->tail, memory_order_relaxed);
+    if (head == tail) { // buffer empty?
+        return (RingBufCtr)(me->end - 1U);
+    }
+    else if (head < tail) {
+        return (RingBufCtr)(tail - head - 1U);
+    }
+    else {
+        return (RingBufCtr)(me->end + tail - head - 1U);
+    }
+}
+
+//............................................................................
+void RingBuf_process_all(RingBuf * const me, RingBufHandler handler) {
+    RingBufCtr tail = atomic_load_explicit(&me->tail, memory_order_relaxed);
+    RingBufCtr head = atomic_load_explicit(&me->head, memory_order_acquire);
+    while (head != tail) { // buffer NOT empty?
+        (*handler)(me->buf[tail]);
+        ++tail;
+        if (tail == me->end) {
+            tail = 0U;
+        }
+        atomic_store_explicit(&me->tail, tail, memory_order_release);
+    }
+}

+ 97 - 0
ymodem/ring_buf.h

@@ -0,0 +1,97 @@
+//============================================================================
+// Lock-Free Ring Buffer (LFRB) for embedded systems
+// GitHub: https://github.com/QuantumLeaps/lock-free-ring-buffer
+//
+//                    Q u a n t u m  L e a P s
+//                    ------------------------
+//                    Modern Embedded Software
+//
+// Copyright (C) 2005 Quantum Leaps, <state-machine.com>.
+//
+// SPDX-License-Identifier: MIT
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//============================================================================
+#ifndef RING_BUF_H
+#define RING_BUF_H
+
+#include <stdatomic.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+//! Ring buffer counter/index
+//
+// @attention
+// The following RingBufCtr type is assumed to be "atomic" in a target CPU,
+// meaning that the CPU needs to write the whole RingBufCtr in one machine
+// instruction. An example of violating this assumption would be an 8-bit
+// CPU, which writes uint16_t (2-bytes) in 2 machine instructions. For such
+// 8-bit CPU, the maximum size of RingBufCtr would be uint8_t (1-byte).
+//
+// Another case of violating the "atomic" writes to RingBufCtr type would
+// be misalignment of a RingBufCtr variable in memory, which could cause
+// the compiler to generate multiple instructions to write a RingBufCtr value.
+// Therefore, it is further assumed that all RingBufCtr variables in the
+// following RingBuf struct *are* correctly aligned for "atomic" access.
+//In practice, most C compilers should provide such natural alignment
+// (by inserting some padding into the ::RingBuf struct, if necessary).
+//
+typedef uint16_t RingBufCtr;
+
+//! Ring buffer element type
+//
+// @details
+// The type of the ring buffer elements is not critical for the lock-free
+// operation and does not need to be "atomic". For example, it can be
+// an integer type (uint16_t, uint32_t, uint64_t), a pointer type,
+// or even a struct type. However, the bigger the type the more RAM is
+// needed for the ring buffer and more CPU cycles are needed to copy it
+// into and out of the buffer memory.
+//
+typedef uint8_t RingBufElement;
+
+//! Ring buffer struct
+typedef struct {
+    RingBufElement *buf; //!< pointer to the start of the ring buffer
+    RingBufCtr end;      //!< index of the end of the ring buffer
+
+    //! atomic index to where next element will be inserted
+    _Atomic(RingBufCtr) head;
+
+    //! atomic index to where next element will be removed
+    _Atomic(RingBufCtr) tail;
+} RingBuf;
+
+void RingBuf_ctor(RingBuf * const me,
+                  RingBufElement sto[], RingBufCtr sto_len);
+RingBufCtr RingBuf_num_free(RingBuf * const me);
+bool RingBuf_put(RingBuf * const me, RingBufElement const el);
+bool RingBuf_get(RingBuf * const me, RingBufElement *pel);
+
+//! Ring buffer callback function for RingBuf_process_all()
+//
+// @details
+// The callback processes one element and runs in the context of
+// RingBuf_process_all().
+//
+typedef void (*RingBufHandler)(RingBufElement const el);
+
+void RingBuf_process_all(RingBuf * const me, RingBufHandler handler);
+
+#endif // RING_BUF_H

+ 0 - 0
ymodem/ymodem.c


+ 1 - 0
ymodem/ymodem.go

@@ -0,0 +1 @@
+package ymodem

+ 0 - 0
ymodem/ymodem.h


+ 0 - 0
ymodem/ymodem_test.c


+ 1 - 0
ymodem/ymodem_test.go

@@ -0,0 +1 @@
+package ymodem