2016-08-30 4 views
-2

Я пытаюсь сократить идентификатор процессора моего микроконтроллера (STM32F1).Как удалить идентификатор CPU в C

Идентификатор процессора состоит из 3-х слов (3 х 4 байта). Это строка id, построенная из 3-х слов: 980416578761680031125348904

Я нашел очень полезную библиотеку, которая делает это.

Библиотека Hashids и есть код C.

Я пытаюсь создать тестовый код на ПК с помощью «Code Blocks IDE», и код работает.

Но когда я перемещаю код во встроенную сторону (Keil v5 IDE), я получаю сообщение об ошибке в функции strdup(): «неявное объявление функции strdup».

Проблема связана с функцией strdup не является стандартной библиотечной функцией и не входит в string.h.

Я не буду заменять функцию strdup на пользовательскую функцию (которая имитирует поведение strdup), чтобы избежать утечки памяти, поскольку strdup копирует строки, используя malloc.

Есть ли другой подход к сжатию длинных чисел?

Спасибо за помощь!

< --- Приложение --->

Это функция, которая использует strdup.

/* common init */ 
    struct hashids_t * 
    hashids_init3(const char *salt, size_t min_hash_length, const char *alphabet) 
    { 
    struct hashids_t *result; 
    unsigned int i, j; 
    size_t len; 
    char ch, *p; 

    hashids_errno = HASHIDS_ERROR_OK; 

    /* allocate the structure */ 
    result = _hashids_alloc(sizeof(struct hashids_t)); 
    if (HASHIDS_UNLIKELY(!result)) { 
     hashids_errno = HASHIDS_ERROR_ALLOC; 
     return NULL; 
    } 

    /* allocate enough space for the alphabet and its copies */ 
    len = strlen(alphabet) + 1; 
    result->alphabet = _hashids_alloc(len); 
    result->alphabet_copy_1 = _hashids_alloc(len); 
    result->alphabet_copy_2 = _hashids_alloc(len); 
    if (HASHIDS_UNLIKELY(!result->alphabet || !result->alphabet_copy_1 
     || !result->alphabet_copy_2)) { 
     hashids_free(result); 
     hashids_errno = HASHIDS_ERROR_ALLOC; 
     return NULL; 
    } 

    /* extract only the unique characters */ 
    result->alphabet[0] = '\0'; 
    for (i = 0, j = 0; i < len; ++i) { 
     ch = alphabet[i]; 
     if (!strchr(result->alphabet, ch)) { 
      result->alphabet[j++] = ch; 
     } 
    } 
    result->alphabet[j] = '\0'; 

    /* store alphabet length */ 
    result->alphabet_length = j; 

    /* check length and whitespace */ 
    if (result->alphabet_length < HASHIDS_MIN_ALPHABET_LENGTH) { 
     hashids_free(result); 
     hashids_errno = HASHIDS_ERROR_ALPHABET_LENGTH; 
     return NULL; 
    } 
    if (strchr(result->alphabet, ' ')) { 
     hashids_free(result); 
     hashids_errno = HASHIDS_ERROR_ALPHABET_SPACE; 
     return NULL; 
    } 

    /* copy salt */ 
    result->salt = strdup(salt ? salt : HASHIDS_DEFAULT_SALT); 
    result->salt_length = (unsigned int) strlen(result->salt); 

    /* allocate enough space for separators */ 
    result->separators = _hashids_alloc((size_t) 
     (ceil((float)result->alphabet_length/HASHIDS_SEPARATOR_DIVISOR) + 1)); 
    if (HASHIDS_UNLIKELY(!result->separators)) { 
     hashids_free(result); 
     hashids_errno = HASHIDS_ERROR_ALLOC; 
     return NULL; 
    } 

    /* non-alphabet characters cannot be separators */ 
    for (i = 0, j = 0; i < strlen(HASHIDS_DEFAULT_SEPARATORS); ++i) { 
     ch = HASHIDS_DEFAULT_SEPARATORS[i]; 
     if ((p = strchr(result->alphabet, ch))) { 
      result->separators[j++] = ch; 

      /* also remove separators from alphabet */ 
      memmove(p, p + 1, 
       strlen(result->alphabet) - (p - result->alphabet)); 
     } 
    } 

    /* store separators length */ 
    result->separators_count = j; 

    /* subtract separators count from alphabet length */ 
    result->alphabet_length -= result->separators_count; 

    /* shuffle the separators */ 
    hashids_shuffle(result->separators, result->separators_count, 
     result->salt, result->salt_length); 

    /* check if we have any/enough separators */ 
    if (!result->separators_count 
     || (((float)result->alphabet_length/(float)result->separators_count) 
       > HASHIDS_SEPARATOR_DIVISOR)) { 
     unsigned int separators_count = (unsigned int)ceil(
      (float)result->alphabet_length/HASHIDS_SEPARATOR_DIVISOR); 

     if (separators_count == 1) { 
      separators_count = 2; 
     } 

     if (separators_count > result->separators_count) { 
      /* we need more separators - get some from alphabet */ 
      int diff = separators_count - result->separators_count; 
      strncat(result->separators, result->alphabet, diff); 
      memmove(result->alphabet, result->alphabet + diff, 
       result->alphabet_length - diff + 1); 

      result->separators_count += diff; 
      result->alphabet_length -= diff; 
     } else { 
      /* we have more than enough - truncate */ 
      result->separators[separators_count] = '\0'; 
      result->separators_count = separators_count; 
     } 
    } 

    /* shuffle alphabet */ 
    hashids_shuffle(result->alphabet, result->alphabet_length, 
     result->salt, result->salt_length); 

    /* allocate guards */ 
    result->guards_count = (unsigned int) ceil((float)result->alphabet_length 
              /HASHIDS_GUARD_DIVISOR); 
    result->guards = _hashids_alloc(result->guards_count + 1); 
    if (HASHIDS_UNLIKELY(!result->guards)) { 
     hashids_free(result); 
     hashids_errno = HASHIDS_ERROR_ALLOC; 
     return NULL; 
    } 

    if (HASHIDS_UNLIKELY(result->alphabet_length < 3)) { 
     /* take some from separators */ 
     strncpy(result->guards, result->separators, result->guards_count); 
     memmove(result->separators, result->separators + result->guards_count, 
      result->separators_count - result->guards_count + 1); 

     result->separators_count -= result->guards_count; 
    } else { 
     /* take them from alphabet */ 
     strncpy(result->guards, result->alphabet, result->guards_count); 
     memmove(result->alphabet, result->alphabet + result->guards_count, 
      result->alphabet_length - result->guards_count + 1); 

     result->alphabet_length -= result->guards_count; 
    } 

    /* set min hash length */ 
    result->min_hash_length = min_hash_length; 

    /* return result happily */ 
    return result; 
} 
+0

Вы можете разместить код, где используется 'strdup'? –

+0

* потому что strdup копирует строки, используя malloc * - Почему это будет проблемой? –

+0

Вы можете 'strcpy()' строку в автоматический буферный массив (или вручную эмулировать такой 'strcpy()'), если вы хотите избежать распределения динамической памяти. Для этого требуется либо поддержка VLA, либо предварительное знание верхней границы размера строки, которую вы скопируете. –

ответ

2

Истинный вопрос, кажется,

Есть другой подход, чтобы сжать длинные номера?

Есть много. Они различаются в нескольких отношениях, в том числе, какие биты ввода вносят вклад в вывод, сколько входов сопоставляется с одним и тем же выходом и каким образом преобразования ввода оставляют выход неизменным.

В качестве простейшего примера, вы можете сжать вход на один бит любым из этих подходов:

  • Выберите бит низшего порядка на входе
  • Выберите бит высшего порядка из вход
  • выход всегда 1
  • т.д.

Или вы можете сжимать до 7 бит, используя число 1 бит на входе в качестве выхода.

Ни один из этих конкретных вариантов, вероятно, вас не интересует, конечно.

Возможно, вам больше будет интересно создавать 32-разрядные выходы для ваших 96-битных входов. Обратите внимание, что в этом случае в среднем будет не менее 2 возможных входов, которые сопоставляются с каждым возможным выходом. Это зависит только от размеров ввода и вывода, а не от каких-либо деталей преобразования.

Например, предположим, что у вас есть

uint32_t *cpuid = ...; 

указывая на аппаратное обеспечение CPU ID. Вы можете произвести 32-битное значение из него, который зависит от всех битов на входе, просто сделать это:

uint32_t cpuid32 = cpuid[0]^cpuid[1]^cpuid[2]; 

ли, что бы удовлетворить ваши цели зависит от того, как вы собираетесь его использовать.

+0

Спасибо, Джон! Вы понимаете проблему! Я думаю, что 2^64 различных выхода будет хорошо! Мои встроенные системы на поле будут намного меньше. – Federico

+0

@Federico, вы, кажется, не понимаете ограничений здесь. У вас будет 2^32 различных выхода. И 2^64 из 96-битных строк приведут к тому же самому результату. В примере xor (^) cpuid32 идентификатора с тем же битом, установленным в cpuid [0] и [1] и [2], будет таким же, как и другой cpuid, где все они очищены ... Как Джон отмеченный выше в комментариях, если все 96 бит должны быть уникальными, нет способа сжать ... – Ross

+1

В качестве примечания, чтобы согласиться с этим, посмотрите справочное руководство STM32, для каких полей введите ID. Некоторые из них более полезны, чем другие, некоторые не изменятся вообще для данного номера детали. Вы должны быть в состоянии выбрать меньшее подмножество из 96 бит, которое обеспечит большую часть уникальности идентификатора (такие вещи, как X, Y позиция на пластине, номер вафли и номер партии). – rjp

1

Вы можете легко реализовать strdup себя так:

char* strdup (const char* str) 
{ 
    size_t size = strlen(str); 
    char* result = malloc(size); 
    if(result != NULL) 
    { 
    memcpy(result, str, size+1); 
    } 
    return result; 
} 

При этом, используя malloc или strdup на встроенной системе, скорее всего, просто нонсенс практика, see this. Также вы не будете использовать числа с плавающей запятой. В целом, эта библиотека, похоже, была написана человеком, ориентированным на компьютер.

Если вы реализуете что-то вроде, например, цепочки хеш-таблиц во встроенной системе, вы должны использовать статически выделенный пул памяти, а не malloc. По этой причине я, вероятно, поеду с непривязанным (по дубликатам, выберите следующее свободное место в буфере).

+0

OP сказал: «Я не буду заменять функцию strdup на пользовательскую функцию (которая имитирует поведение strdup), чтобы избежать утечки памяти, поскольку strdup копирует строки, используя malloc». –

+1

Я знаю, что он попросил 'strdup()' mimic, но он также говорит, что хочет избежать динамического распределения памяти. Это оставляет мне неуверенность в том, чего он * хочет, но я не думаю, что это так. –

+0

Этот ответ указывает, что malloc, вероятно, вообще не имеет никакого смысла начинать. – Lundin

0

Уникальный идентификатор идентификатора устройства (96 бит) расположен по адресу 0x1FFFF7E8. Он запрограммирован на заводе и доступен только для чтения. Вы можете прочитать его напрямую, не используя какую-либо другую внешнюю библиотеку. Например:

unsigned int b = *(0x1FFFF7E8); 

должен предоставить вам первые 32 бита (31: 0) уникального идентификатора устройства. Если вы хотите, чтобы получить строку, как и в случае библиотеки упоминалась, следующие должны работать:

sprintf(id, "%08X%08X%08X", *(0x1FFFF7E8), *(0x1FFFF7E8 + 4), *(0x1FFFF7E8 + 8); 

Некоторая дополнительная отливка может потребоваться, но в целом это то, что библиотека сделала. Более подробную информацию см. В справочном руководстве STM32F1xx (RM0008), раздел 30.2. Точная ячейка памяти для чтения отличается от семейства Cortex-M4 MCU.

+0

Я делаю именно это. Но проблема не связана с «Как получить идентификатор CPU», но «Как сжать цифры идентификатора процессора». – Federico

+0

О, у меня есть ваш вопрос, извините за путаницу. Я оставлю свой комментарий на случай, если кто-то его найдет. –

Смежные вопросы