Garmin
Member
Только начинаю писать свои программы для ESP8266. Установил UDK, компилирую учебные проекты.
При попытке разобраться с имеющимися примерами я был просто в шоке от стиля написания программ. Про форматирование текста я не говорю, но сумасшедшие макросы и дефайны делают программу нечитаемой и только условно работающей. Например, макрос
[inline]PIN_FUNC_SELECT(PIN_NAME, FUNC)[/inline]
вообще не компилируется без предупреждений, пришлось заменить его инлайн функцией.
Но я хочу поговорить о другом: о доступе к регистрам. Применяемые макросы типа
[inline] WRITE_PERI_REG (SPI_USER2 (HSPI), regvalue);[/inline]
или
[inline]SET_PERI_REG_MASK (SPI_CMD (HSPI), SPI_USR);//transmission start[/inline]
без комментариев совершенно непонятны.
Я написал пример описания регистров SPI в том стиле, к которому привык - как описаны регистры в процессорах STM. При этом регистры описаны дважды: в виде битовых полей и в виде битовых масок. Попробовал скомпилировать и в виде битовых масок, и в виде битовых полей - прошло без ошибок.
Пример старого и нового подхода:
У меня не хватает опыта работы в Eclipse, чтобы сравнить ассемблерный выход между старыми макросами и новыми выражениями. Проект с файлами я выложил на гитхаб.
Если кому это интересно, посмотрите файлы spi.c, spi.h и eagle_soc.h и проверьте, правильно ли компилятор обрабатывает новые определения.
При попытке разобраться с имеющимися примерами я был просто в шоке от стиля написания программ. Про форматирование текста я не говорю, но сумасшедшие макросы и дефайны делают программу нечитаемой и только условно работающей. Например, макрос
[inline]PIN_FUNC_SELECT(PIN_NAME, FUNC)[/inline]
вообще не компилируется без предупреждений, пришлось заменить его инлайн функцией.
Но я хочу поговорить о другом: о доступе к регистрам. Применяемые макросы типа
[inline] WRITE_PERI_REG (SPI_USER2 (HSPI), regvalue);[/inline]
или
[inline]SET_PERI_REG_MASK (SPI_CMD (HSPI), SPI_USR);//transmission start[/inline]
без комментариев совершенно непонятны.
Я написал пример описания регистров SPI в том стиле, к которому привык - как описаны регистры в процессорах STM. При этом регистры описаны дважды: в виде битовых полей и в виде битовых масок. Попробовал скомпилировать и в виде битовых масок, и в виде битовых полей - прошло без ошибок.
Пример старого и нового подхода:
Код:
pin_func_select (PERIPHS_IO_MUX_MTDI_U, 2); //configure io12 to hspi_miso mode
pin_func_select (PERIPHS_IO_MUX_MTCK_U, 2);//configure io13 to Hspi_mosi mode
pin_func_select (PERIPHS_IO_MUX_MTMS_U, 2);//configure io14 to Hspi_clk mode
pin_func_select (PERIPHS_IO_MUX_MTDO_U, 2);//configure io15 to Hspi_cs mode
// использование регистров
SPI1->spi_user |= SPI_USER_CS_SETUP | SPI_USER_CS_HOLD | SPI_USER_COMMAND;
SPI1->spi_user &= ~SPI_USER_FLASH_MODE;
SPI1->spi_clock_bits.equ_sysclk = 0;
SPI1->spi_clock_bits.pre_s = SPI_PREDIV_CLK;
SPI1->spi_clock_bits.clkcnt_n = SPI_DIV_CLK_N;
SPI1->spi_clock_bits.clkcnt_h = SPI_DIV_CLK_H;
SPI1->spi_clock_bits.clkcnt_l = SPI_DIV_CLK_L;
// использование макросов
SET_PERI_REG_MASK (SPI_USER (HSPI),
SPI_CS_SETUP | SPI_CS_HOLD | SPI_USR_COMMAND);
CLEAR_PERI_REG_MASK (SPI_USER (HSPI), SPI_FLASH_MODE);
WRITE_PERI_REG (SPI_CLOCK (HSPI),
((SPI_PREDIV_CLK & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S)
| ((SPI_DIV_CLK_N & SPI_CLKCNT_N) << SPI_CLKCNT_N_S)
| ((SPI_DIV_CLK_H & SPI_CLKCNT_H) << SPI_CLKCNT_H_S)
| ((SPI_DIV_CLK_L & SPI_CLKCNT_L) << SPI_CLKCNT_L_S));//clear bit 31, set SPI clock div
Если кому это интересно, посмотрите файлы spi.c, spi.h и eagle_soc.h и проверьте, правильно ли компилятор обрабатывает новые определения.