ESP8266 CCLOCK Странное поведение
Я пытаюсь написать очень быстрый код для ESP8266, поэтому я пытаюсь понять, как рассчитать время. Я обнаружил CCLOCK
, регистр, который отражает количество тактов с момента запуска. (https://github.com/esp8266/Arduino/issues/4632#issuecomment-380632906 и другие ссылки.) Однако при тестировании я столкнулся с некоторым странным поведением. Рассмотрим следующий код:
static inline volatile uint32_t asm_ccount(void) {
uint32_t r;
asm volatile ("rsr %0, ccount" : "=r"(r));
return r;
}
char outgoingPacket[4];
...
void loop() {
// ... некоторые вещи ...
uint32_t startTime = asm_ccount();
uint32_t stopTime = asm_ccount();
uint32_t elapsed = stopTime-startTime;
outgoingPacket[0] = (elapsed >> 24) & 0xff;
outgoingPacket[1] = (elapsed >> 16) & 0xff;
outgoingPacket[2] = (elapsed >> 8) & 0xff;
outgoingPacket[3] = elapsed & 0xff;
Udp.beginPacket(targetUdpIp, targetUdpPort);
Udp.write(outgoingPacket, 4);
Udp.endPacket();
}
(На моем компьютере для получения этих сообщений запущен в основном следующий код Java:)
while (true) {
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
byte[] data = packet.getData();
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < packet.getLength(); i++) {
sb1.append(String.format("%8s", Integer.toString(((int) data[i]) & 0xFF, 2)).replace(' ', '0'));
sb2.append(String.format("%2s", Integer.toString(((int) data[i]) & 0xFF, 16)).replace(' ', '0'));
}
System.out.println(sb1 + " " + Integer.parseInt(sb2.toString(), 16));
}
(Да, я знаю, это немного хакерски, но результаты кажутся правильными.)
Теперь в большинстве случаев результат выглядит так
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000000000000001 1
Но примерно в 5 разах из 77 000 я получу такие строки, как
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000000110101000 424
00000000000000000000000000000001 1
00000000000000000000000000000001 1
...
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000010010100001 1185
00000000000000000000000000000001 1
00000000000000000000000000000001 1
...
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000010001001100 1100
00000000000000000000000000000001 1
00000000000000000000000000000001 1
Я выполнял код в течение 1 минуты 4 секунд и получил 3 счета из 424, 1 из 1100 и 1 из 1185. Кажется особенно странным, что 424 появляется три раза.
Учитывая, что, насколько я понимаю, соответствующие строки кода (два вызова asm_ccount
) должны были быть скомпилированы с заданным набором инструкций, я ожидал, что это займет каждый раз точно такое же количество циклов.
Почему этого не происходит?
Это прерывает? Что-то кэширует? Этот регистр на самом деле не работает, как заявлено или как я понимаю? Я сделал что-то глупое в коде передачи или регистрации? Что-то еще?
@Erhannis, 👍0
Обсуждение1 ответ
Лучший ответ:
У вас есть прерывания, которые прерывают ваш код. Для их выполнения требуется несколько циклов.
- Как читать и записывать EEPROM в ESP8266
- Как сделать выводы Tx и Rx на ESP-8266-01 в выводах GPIO?
- Как навсегда изменить скорость передачи данных ESP8266 (12e)?
- Как заставить 5-вольтовое реле работать с NodeMCU
- Как исправить: Invalid conversion from 'const char*' to 'char*' [-fpermissive]
- ESP8266 не подключается к Wi-Fi
- AT-команда не отвечает на последовательный монитор
- Разница между этими двумя платами NodeMCU?
У вас есть прерывания, которые прерывают ваш код. Для их запуска требуется несколько циклов., @Delta_G
Ах ах! Я думаю ты прав. Когда я отключаю прерывания вокруг критического кода, его синхронизация становится почти идеально стабильной. ...Но затем он перестает работать после нескольких десятков циклов, так что я не могу этого сделать, ха-ха. Если вы хотите сделать свой комментарий ответом, я приму его., @Erhannis