Ahora tenemos una sección de Discusiones de Github. Cuando un problema es definitivamente un defecto en el núcleo, reducirá el tiempo necesario para solucionarlo si crea un problema, ya que priorizo los problemas antes que ponerse al día con las discusiones.
Esto corrige muchos de los errores presentes en 2.6.x.
2.6.x introduce una huella flash mejorada significativamente en serie al mismo tiempo que agrega funciones, el cable puede despertar al esclavo del modo de suspensión sin dañar los datos y mucho, mucho más, consulte el Registro de cambios.
Sólo se deben utilizar versiones del IDE de Arduino descargadas desde arduino.cc, NUNCA desde un administrador de paquetes de Linux. Los administradores de paquetes a menudo tienen el IDE de Arduino, pero lo han modificado . Esto a pesar de que no saben nada sobre Arduino o el desarrollo integrado en general, y mucho menos lo que necesitarían saber para modificarlo con éxito. Esas versiones son conocidas por los problemas sutiles pero graves causados por estas modificaciones imprudentes. No se debe esperar que este núcleo funcione en dichas versiones, y no se realizarán modificaciones para corregir las versiones del IDE que provienen de los administradores de paquetes por este motivo.
Este es un error en el cliente Arduino.
Las versiones de IDE entre 1.8.13 y 2.x desarrollaron defectos novedosos importantes. Sin embargo, las versiones 1.8.2 y anteriores del IDE poseen defectos devastadores no solucionados. Creo que finalmente tienen una versión funcional del IDE y creo que la última versión puede instalar mi núcleo correctamente.
Antes de megaTinyCore 2.6.0, la instalación manual de megaTinyCore causaba que la V1.8.14 del IDE fallara debido a este error cuando instala el núcleo manualmente en su carpeta arduino. Los usuarios de 1.8.14 y posteriores deben usar la versión 2.6.0 de megaTinyCore.
Compro muchos productos electrónicos en AliExpress. Es un gran mercado para cosas fabricadas por empresas chinas y en su mayoría genéricas, incluidos muchos componentes que no están disponibles para las personas en el Occidente global de ninguna otra manera (por ejemplo, el pedido mínimo es un carrete o algo así, si es que puedes encontrar un proveedor de componentes que trabaja con el fabricante chino de chips sin nombre). No es un buen lugar para las últimas líneas de productos semiconductores de los principales fabricantes occidentales, especialmente en medio de una escasez histórica de dichos chips. Con frecuencia se informa que los dispositivos AVR modernos, cuando están disponibles a través de esos canales, son falsos o defectuosos (como los ATtiny412 que piensan que son 416 y es posible que no ejecuten correctamente el encendido al reiniciar). De hecho, probablemente no quieras comprar ningún microcontrolador AVR en AliExpress ... Las placas ensambladas, como los clones de Arduino Nano, generalmente funcionan si evitas las que tienen chips LGT8 de terceros y ten cuidado con las que tienen ATmega168p. en lugar del '328p, pero hay muchos informes de microcontroladores falsos cuando se venden como chips básicos (he oído hablar de ATtiny85 falsos que en realidad fueron comentados ATtiny13s; no son sólo los AVR modernos los que se falsifican). Hay muchas teorías interesantes sobre el origen de esos chips falsos, y Microchip ha guardado silencio total sobre el tema.
Este documento se ve mejor en línea (en lugar de abrir el archivo de rebajas en su editor de texto favorito), para que se pueda hacer clic en los enlaces y se muestren las imágenes en línea, y probablemente lo más importante, para que a veces las tablas se representen correctamente. Nuevamente, este [documento se puede encontrar en github](https://github.com/SpenceKonde/megaTinyCore](https://github.com/SpenceKonde/megaTinyCore)
Las versiones anteriores no manejan adecuadamente a los programadores en el menú herramientas -> programadores, lo que degrada la UX rápidamente a medida que aumenta la cantidad de núcleos instalados. No son adecuados. Las versiones más recientes que comienzan con 1.8.14 (incluidas 1.8.17, 1.8.18 y 1.8.19) pueden generar un error de "pánico: no se encontró una versión principal" porque no pueden analizar correctamente el archivo platform.txt. Desde la versión 2.6.0 hemos estado modificando manualmente el archivo platform.txt directamente antes del lanzamiento, por lo que esto es un problema menor.
Cuando megaTinyCore se instala a través del administrador de placa, la versión requerida de la cadena de herramientas se instala automáticamente. Todas las piezas de la serie 0/1/2 son compatibles sin pasos adicionales. Hasta 2.2.7, usamos la versión Arduino7 de avr-gcc (gcc 7.3.0 y avrlibc 3.6.1) con los últimos ATpacks a partir de junio de 2020. A partir de 2.2.7, comenzamos a usar mi compilación Azduino de la cadena de herramientas, que ha actualizado ATpacks para todas las piezas recientemente compatibles. 2.2.7 usó Azduino3, 2.3.0+ usó Azduino4 y, a partir de 2.6.0, usamos Azduino5 (aunque no nos ofrece ningún beneficio, aparte de ahorrar un cuarto de GB de espacio en el disco duro y 40 MB de ancho de banda de descarga si instala ambos). megaTinyCore y DxCore a través del administrador de la junta.
La instalación manual es más complicada, especialmente si desea compatibilidad con la Serie 2; consulte la guía de instalación para obtener más información.
Un núcleo Arduino para tinyAVR Serie 0, Serie 1 y ahora Serie 2. Estas partes tienen una arquitectura mejorada en comparación con las partes "clásicas" de tinyAVR (que son compatibles con ATTinyCore), con periféricos mejorados y tiempo de ejecución mejorado para ciertas instrucciones (éstas son similares en ambos aspectos a la avanzada AVR Dx-Series, así como Chips megaAVR 0-Series como el ATmega4809 tal como se usa en el Nano Every y Uno Wifi Rev. 2 oficial (aunque el equipo de Arduino ha hecho todo lo posible para derrotarlos) en los paquetes pequeños y de bajo costo típicos. de la línea ATtiny. Todas estas piezas cuentan con al menos un UART de hardware y una interfaz SPI y TWI (nada de esa basura USI como, por ejemplo, el ATtiny85), un potente sistema de eventos, lógica personalizada configurable, al menos un comparador analógico en chip. , un oscilador interno sorprendentemente preciso y, en el caso de la Serie 1, un canal de salida DAC real y, en el caso de la Serie 2, un elegante ADC diferencial.
Además, las piezas de la serie tinyAVR 0/1/2 son baratas : las piezas de gama alta, el 3226 y el 3227, con 32k de flash y 3k de SRAM (frente a los 2k SRAM del ATmega328p utilizado en Uno/Nano/ProMini). poco más de $1 USD en cantidad, menos que muchas piezas AVR ATtiny clásicas de 8k ("conjunto de instrucciones AVR, a precio PIC"). Todas estas piezas están clasificadas para funcionar a 16 MHz o 20 MHz (a 4,5-5,5 V) sin un cristal externo, y el oscilador interno es lo suficientemente preciso para la comunicación UART.
Estos utilizan programación UPDI, no ISP tradicional como lo hacían las piezas clásicas de ATtiny. Consulte a continuación para obtener más información. Obtener un programador UPDI es simple: puede usar un Arduino clásico basado en 328p como programador usando jtag2updi, o para obtener mejores resultados con hardware más económico, puede usar cualquier adaptador serie USB y una resistencia (y preferiblemente un diodo) usando el SerialUPDI incluido. herramienta, o puede usar AVRdude con uno de los programadores de Microchip (los programadores basados en mEDBG/nEDBG/EDBG en su placa de desarrollo, Atmel-ICE o SNAP) o cualquier herramienta de programación UPDI que emule una de esas (que, que yo sepa, todas lo hacen; si hay una que avrdude admite y que mi núcleo no, ¡abra un problema para hacérmelo saber!).
En estas partes se admite un gestor de arranque en serie, Optiboot_x (basado en el mismo código base que el gestor de arranque Arduino Uno clásico, aunque muy modificado) (el soporte de la serie 0/1 está actualmente activo, se espera la serie 2 para la primera semana de mayo). ; los ajustes para las piezas nuevas son triviales), lo que permite programarlas a través de un puerto serie tradicional. Consulte la sección Optiboot a continuación para obtener más información sobre esto y las opciones relevantes. La instalación del gestor de arranque requiere un programador UPDI. Las placas de conexión ensambladas que vendo en Tindie están disponibles precargadas (se cargan bajo demanda). Dicho esto, la experiencia del usuario con Optiboot es un poco decepcionante en las piezas de la serie 0/1, así como en las piezas de la serie 2 de 14 pines, debido a la falta de un pin de reinicio de hardware que pueda usarse con el circuito de reinicio automático habitual. para restablecerse automáticamente en el gestor de arranque cuando se abre el puerto serie. Debe deshabilitar completamente la programación UPDI (se requiere un programador HV si es necesario cambiar la configuración de los fusibles o el cargador de arranque después del arranque inicial) o dejar UPDI habilitado, pero iniciar cualquier carga dentro de los 8 segundos de aplicar energía. Las piezas de la Serie 2 de 20 y 24 pines admiten un "pin de reinicio alternativo" que les permite actuar más como un Arduino tradicional.
La interfaz de programación UPDI es una interfaz de un solo cable para programación (y depuración: interfaz universal de programación y depuración ), que se utiliza en la serie tinyAVR 0/1/2, así como en todos los demás microcontroladores AVR modernos. . Si bien siempre se puede comprar un programador UPDI específico de Microchip, esto no se recomienda cuando se va a utilizar el IDE de Arduino en lugar del IDE (terriblemente complicado) de Microchip. Hay numerosos informes de problemas en Linux para los programadores oficiales de Microchip. Hay dos enfoques alternativos de muy bajo costo para crear un programador UPDI, y en ambos la comunidad Arduino tiene más experiencia que los programadores oficiales.
Antes de que existiera megaTinyCore, existía una herramienta llamada pyupdi, un programa Python simple para cargar microcontroladores equipados con UPDI utilizando un adaptador en serie modificado mediante la adición de una sola resistencia. Pero pyupdi no se podía utilizar fácilmente desde el IDE de Arduino, por lo que esta no era una opción. A partir de la versión 2.2.0, megaTinyCore incorpora una implementación portátil de Python, que abre muchas puertas; Originalmente estábamos planeando adaptar pyupdi, pero a instancias de su autor y varios empleados de Microchip, hemos basado esta funcionalidad en pymcuprog, una herramienta "más robusta" desarrollada y "mantenida por Microchip" que incluye la misma carga de puerto serie. característica, solo que sin las optimizaciones de rendimiento. Si realiza la instalación manualmente, debe agregar el paquete Python apropiado para su sistema operativo para poder utilizar este método de carga (una instalación del sistema Python no es suficiente ni necesaria).
Lea la documentación de SerialUPDI para obtener información sobre el cableado.
A partir de 2.3.2, con las espectaculares mejoras en el rendimiento y la confiabilidad comprobada del esquema de cableado que utiliza un diodo en lugar de una resistencia, y en vista de la debilidad del firmware jtag2updi, este es ahora el método de programación recomendado. A partir de esta versión, la velocidad de programación se ha incrementado hasta en un factor de 20 y ahora supera con creces lo que era posible con jtag2updi (la programación a través de jtag2updi es aproximadamente comparable en velocidad a la programación a través de SerialUPDI en la opción de velocidad "LENTA", 57600 baudios; la versión normal de 230400 baudios se programa aproximadamente tres veces más rápido que la versión LENTA o jtag2updi, mientras que la opción "TURBO" (se ejecuta a 460800 baudios y aumenta la velocidad de carga en aproximadamente un 50% con respecto a la normal. La versión de velocidad TURBO solo debe usarse con dispositivos que funcionen a 4.5v o más, ya que tenemos que ejecutar el reloj UPDI más rápido para mantener el ritmo (tampoco es lo esperado). para ser compatible con todos los adaptadores serie (ésta es una compensación intencional para mejorar el rendimiento), pero permite cargar y verificar un boceto de 32 kB en 4 segundos.
Se están iterando tres diseños: un adaptador serial de doble puerto donde ambos son puertos seriales, un adaptador serial de doble puerto donde un puerto es siempre UPDI y un puerto único con un interruptor para seleccionar el modo y una placa adicional opcional para proporcionar Leds indicadores del estado de las líneas de control del módem.
Estos permitirán el uso de un conector SMT JST-XH o un conector Dupont, de cualquier manera con 6 pines para serie (distribución de pines FTDI como está marcado) y 3 pines (para UPDI).
Los tres podrán suministrar 3.3 o Vusb (nom. 5V), o desconectar tanto Vusb como 3V3 de la alimentación, y esperar que el dispositivo de destino reciba alimentación con 5.5V > Vdd > 1.8V. Los niveles lógicos utilizados en este caso serán el voltaje de lo que se aplique. ¡Tenga en cuenta que en dispositivos seriales duales, el riel de alimentación VccIO se comparte! Ambos deben estar funcionando al mismo voltaje, ser el mismo dispositivo o el adaptador debe estar configurado para alimentarlos y desconectar su alimentación.
Según el modelo del adaptador y el sistema operativo, se ha descubierto que se requieren diferentes configuraciones de sincronización; sin embargo, las configuraciones necesarias para evitar que incluso 230400 baudios fallen en Linux/Mac con la mayoría de los adaptadores imponen una penalización de tiempo mucho mayor en Windows, donde el manejo en serie del sistema operativo es lo suficientemente lento como para que nada necesite ese retraso...
El "retraso de escritura" mencionado aquí es para permitir que el comando de borrado y escritura de página termine de ejecutarse; esto lleva un tiempo distinto de cero. Dependiendo del adaptador, la latencia USB y el buffer implícito de 2 o 3 bytes (es como un USART, y probablemente implementado como tal internamente. El tercer byte que llega no tiene adónde ir, porque el buffer de hardware tiene solo 2 bytes de profundidad) puede ser suficiente para permitirle funcionar sin un retraso explícito. O puede fallar a la mitad e informar un "Error con st". Cuanto más rápido sea el tiempo de espera de latencia del adaptador y más rápido sea el manejo de serie del sistema operativo, mayores serán las posibilidades de que esto sea un problema. Esto está controlado por el parámetro de línea de comando -wd
si se ejecuta prog.py manualmente. A partir de 2.5.6, este retraso de escritura está más cerca del tiempo real solicitado (en ms), anteriormente tenía una granularidad de varios ms, cuando 1 es todo lo que necesitaba y, como resultado, la penalización que impuso fue brutal , particularmente en Ventanas.
Guía de selección:
Los adaptadores FTDI (FT232, FT2232 y FT4232, etc.), incluidos los falsos que están disponibles en eBay/AliExpress por alrededor de $2, en Windows tienen por defecto un período de latencia insoportablemente largo de 16 ms. Incluso con los esfuerzos que hacemos para limitar la cantidad de períodos de retraso de latencia que debemos esperar, esto prolongará una carga de 2,2 segundos a más de 15 segundos. Debes cambiar esto para obtener velocidades de carga tolerables:
Se puede fabricar uno a partir de un AVR Uno/Nano/Pro Mini clásico; Los nanoclones económicos son la opción habitual, ya que son lo suficientemente baratos como para conectarlos y dejarlos así. Ya no proporcionamos documentación detallada para estos procesos; jtag2updi está en desuso. Si todavía lo está usando, debe seleccionar jtag2updi en el menú herramientas->programador. Esta era anteriormente nuestra opción recomendada. Debido a los persistentes errores de jtag2updi y su dependencia de la herramienta 'avrdude', que en gran medida no se mantiene (que, entre otras cosas, inserta un mensaje de error falso en todas las cargas de UPDI realizadas con ella), esto ya no se recomienda.
Aparentemente Arduino no incluye versiones de 32 bits del último avrdude. Definí una nueva definición de herramienta que es una copia de arduino18 (la última), excepto que incorpora la versión 17 en Linux de 32 bits, ya que es la mejor disponible para esa plataforma. La versión arduino17 no admite correctamente la carga con algunas de las herramientas de programación de Microchip.
Actualmente, esto se usa solo para las últimas versiones y debería corregir el error avrdude no disponible para esta plataforma.
Consulte este documento que cubre todos los AVR modernos.
Característica | serie 0 | 1-serie | 1+serie | 2 series |
---|---|---|---|---|
Destello | 2k-16k | 2k-8k | 16k/32k | 4k-32k |
cuenta | 8-24 | 8-24 | 14-24 | 14-24 |
SRAM | 128b-1k | 128b-512b | 2k | 512b-3k |
DCT | No | Sí | Sí | No |
TCB | 1 | 1 | 2 | 2 |
CAD | 1x10 bits | 1x10 bits | 2x10 bits | 1x12 bits con PGA |
pasador VREF | No | No | Sí | Sí |
C.A. | 1 | 1 | 3 | 1 |
Evento * | 3 canales | 6 canales | 6 canales | 6 canales |
CCCL ** | 2 LUT | 2 LUT | 2 LUT | 4 LUT |
*
Los canales de eventos, excepto en los tinyAVR de la serie 2 (y todos los AVR modernos que no son minúsculos), se subdividen en dos tipos: sincrónicos (con el reloj del sistema) y asíncronos. No todos los generadores se pueden usar con un canal sincrónico y algunos usuarios de eventos solo pueden usar los canales sincrónicos, y las listas de canales son menos consistentes y más. Esta locura fue abandonada a la primera oportunidad; incluso el mega0 había eliminado esa distinción.
**
Solo las piezas de 2 series y que no sean pequeñas pueden activar una interrupción según el estado de CCL.
Todas las piezas tienen entrada analógica disponible en la mayoría de los pines (todos los pines en PORTA y PORTB 0-1 y 4-5). El segundo ADC en la serie 1+ también puede usar los pines de PORTC como entradas (consulte la referencia analógica para obtener información sobre su uso).
Estas son las opciones de presupuesto. Aunque son compatibles, no se recomiendan. Estos nunca obtienen el "impulso" que obtiene la serie tinyAVR 1 a 16k, no tienen un segundo TCB en ninguna configuración, ni TCD, solo 3 canales de eventos, ninguno de los cuales puede transportar salida de eventos RTC. Estas piezas tienen 2 CCL LUT como la serie 1 y están disponibles con hasta 16k de flash en configuraciones de 14, 20 y 24 pines (solo 4k para piezas de 8 pines) y hasta 1k SRAM.
Estos tienen 2k, 4k u 8k de flash y 128, 256 o 512b de ram, al igual que la serie 0. No tienen el segundo ADC, la configuración triple AC ni el segundo TCB, aunque sí tienen el TCD.
De repente, a 16k, las partes de la serie 1 se vuelven mucho más interesantes. Acompañando al flash más grande hay un arsenal de periféricos que parecen adecuados para un chip mucho más grande, y ya sean 16k o 32k, todos obtienen 2k de SRAM. Todo el segundo ADC es único entre los AVR. Parece haber sido el campo de pruebas para muchas funciones que aparecieron de forma refinada en la serie AVR Dx. El precio no parece tener en cuenta los periféricos muy superiores de la serie 1 de 16k,
Como puede ver en la tabla anterior, la Serie 2 es casi más una versión secundaria que una actualización. Tienen un ADC mucho mejor, el sistema de eventos y los CCL son "normales" y tienen más RAM, la parte de 14 pines está disponible con 32k de flash (aparentemente se planeó un 3214, pero luego se canceló; llegó lo suficientemente lejos como para estar en el ATPACK por un tiempo antes de ser eliminado)
He escrito un breve resumen de cuándo le gustaría usar qué serie, si la elección correcta no es obvia a estas alturas.
En la definición oficial de la placa Arduino para su paquete de hardware "megaavr", implican que la nueva arquitectura en las piezas megaAVR 0-Series (que es casi la misma que se usa en tinyAVR 0-Series y 1-Series) se llama "megaavr". " - ese no es un término oficial. Microchip utiliza el término "megaAVR" para referirse a cualquier pieza "ATmega", ya sea que tenga periféricos de estilo antiguo o modernos. No existen términos oficiales para referirse a todas las partes de AVR de una familia u otra, y un empleado de Microchip incluso negó que existiera tal término internamente. No estoy seguro de cómo se pueden fabricar dos conjuntos de piezas, teniendo las piezas de cada conjunto tanto en común entre sí y tan poco en común con el otro conjunto, sin que nadie acuñe una frase para referirse a cualquiera de ellas.
En este documento, antes de la versión 2.0.2, utilizamos la convención Arduino y, a pesar de que ha pasado más de un año desde entonces, sigo encontrando lugares donde los llamo megaAVR. Informe esto usando un problema de github si ve alguno. Tenga en cuenta que los términos avr
y megaavr
todavía se usan internamente (por ejemplo, en bibliotecas, para marcar con qué partes es compatible una biblioteca determinada, o para separar diferentes versiones de un archivo según en qué se ejecutarán). Esto continuará; tenemos que seguir con esto por compatibilidad con lo que el equipo Arduino comenzó con el núcleo de Uno WiFi Rev. 2 y Nano Every.
En cualquier caso, se necesita alguna palabra para referirse a los dos grupos y Microchip no la ha proporcionado. En ausencia de un término oficial, me he estado refiriendo a los dispositivos AVR anteriores a 2016 (con registros PORTx, DDRx, etc. para pines) como " AVR clásico " y a los que Arduino llama megaavr como " AVR moderno ". También existen algunas partes cuyos módulos de E/S se parecen más a los AVR clásicos, pero que también tienen una versión significativamente peor del conjunto de instrucciones y tamaños de flash típicos de 1k o menos. Estos usan la variante AVRrc (para núcleo reducido) de AVR, mientras que la mayoría de los AVR clásicos usan AVRe o AVRe+, y los AVR modernos usan AVRxt. Las partes de AVRrc no son compatibles con este núcleo, y en la desafortunada ocasión en que necesite discutir estas partes profundamente decepcionantes, me referiré a ellas como partes de " Núcleo reducido AVR ", ya que ese es su nombre oficial, aunque tengo mucho Frases más coloridas para ellos. Se recomienda que ningún diseño utilice un AVR de núcleo reducido , punto. No es que estén obsoletos, simplemente son pésimos. Se recomienda que los " AVR modernos " (aquellos con los nuevos periféricos y el conjunto de instrucciones AVRxt ), ya sea la serie Ex, la serie Dx, tinyAVR 0/1/2 o mega0, se utilicen para todos los diseños nuevos.
Hoja de datos para la nueva serie tinyAVR 2: si bien la hoja de datos solo "cubre" las 16k piezas, establece claramente que no hay diferencias en las características entre piezas con el mismo número de pines (es decir, no hay piezas "doradas" como la 16k/32k Serie 1), solo entre piezas con diferentes números de pines, y solo según lo dicte el número de pines (es decir, una característica en la parte de 24 pines estará en la de 14 pines, a menos que el Uno de 14 pines no tiene los pines que necesita y es algo que no se puede usar sin pines). Las piezas de 14, 20 y 24 pines se enumeran con flash de 4k, 8k, 16k y 32k; Estas opciones de tamaño de flash, respectivamente, vienen con 512, 1024, 2048 y 3072 bytes de SRAM (es decir, las partes de 4k y 8k tienen el doble de SRAM), las partes de 4/8k obtienen 128 bytes de EEPROM, las más grandes obtienen 256 Las piezas de 14 pines vienen en SOIC y TSSOP, las de 20 pines en SOIC (ancho), SSOP y eso. QFN diminuto como el 1616 (esta vez también nos dieron la parte de 32k en ese paquete, pero buena suerte para conseguir uno, está pendiente de entrega en todas partes; no pude conseguir ni uno solo) y 24 pines en el mismo VQFN que el 3217.
TWI, SPI, USART0, AC0 no han cambiado, al igual que NVMCTRL (los cambios requeridos en el gestor de arranque estaban únicamente en relación con la compatibilidad con el segundo USART). Opciones de reloj sin cambios. TCB0 y TCB1 se actualizaron a la versión de la serie Dx: opción de evento de desconexión, cascada y bits INTCTRL separados para OVF y CAPT (buenas adiciones, pero nada relevante para el núcleo en sí), y todas las piezas tienen ambos TCB. Ahora tenemos 4 LUT CCL y 2 secuenciadores, en lugar de 2 y 1, y pueden disparar interrupciones como otras partes con CCL (y a diferencia de la serie tinyAVR 0/1). Una de las características más interesantes es que, como era de esperar, tienen un segundo USART (ese ruido que escuchas es el ATtiny841 y el ATtiny1634 sollozando en la esquina). Los registros PORTUX ahora tienen el mismo nombre que el resto de los AVR modernos, pero no perdimos el control individual sobre los pines de cada canal TCA WO. EVSYS ahora funciona como lo hace en piezas que no son de la serie tinyAVR-0/1 (lo cual es un cambio bienvenido: la serie 0/1 era la extraña, y algunas de las formas en que su EVSYS era diferente apestaron ). Las funciones de la Serie 1 de TCD0, AC1/2, DAC0 y ADC1 desaparecieron . En su lugar, ADC0 es mucho más elegante y casi irreconocible, el primer AVR nuevo lanzado desde la compra que presentaba un ADC diferencial real. (otro gemido agonizante del pobre '841, que también tiene un ADC increíblemente elegante con excelentes opciones diferenciales, pero que parece completamente anticuado al lado de los nuevos)... a juzgar por el volumen de publicaciones sobre diferentes temas que he Parece que tengo la sensación de que el ADC diferencial no estaba en la parte superior de la mayoría de sus listas de deseos, pero sí en la parte superior de las listas de los principales clientes de chips, y eso es lo que estamos obteniendo. Y ya era hora de que tuviéramos un ADC diferencial adecuado en lugar del de la serie Dx. Y es realmente muy elegante. Vea abajo.
megaTinyCore proporciona una implementación analogRead() y funciones más potentes para usar el sobremuestreo y PGA (consulte la sección de funciones analógicas a continuación).
Ah, y una cosa más... la configuración del pin UPDI tiene las opciones antiguas: UPDI, E/S o Reset... y una nueva: UPDI en PA0, con pin RESET de hardware en PB4. Optiboot finalmente será una opción viable y cómoda al menos en las piezas que tienen PB4, es decir, no las de 14 pines. Que también resulta ser (si las ventas de mi tienda Tindie son una indicación) el tipo más popular.
¿Crees que habrá 3 series? Yo no. DD y EA claramente los están persiguiendo y tomando posiciones estratégicas alrededor del territorio de los tinyAVR. Creo que es sólo cuestión de tiempo antes de que la marca sea eliminada como lo hicieron con megaAVR después de la serie megaAVR 0. Esto no es necesariamente algo malo: todas las piezas de las series Dx y EA son muy similares en cuanto a asignación de pines y comportamiento, lo cual es muy bueno. Los diminutos son menos sistemáticos, aunque distribuyen pines a más periféricos. El principio rector parece haber sido "ningún periférico se quedará atrás". En contraste con las asignaciones de pines de las series Dx y EA, donde todo sigue un plan maestro fijo. Las piezas tienen o no un pin determinado, y si no lo tienen, no tienen esa función disponible. En ambos grupos amplios, creo que hay un gerente de producto cuyo trabajo es golpear a los ingenieros que piensan en hacer una "excepción" al Holy Pinout (ya que esas excepciones inevitablemente proliferan y es como terminamos con las asignaciones de pines de la diana con los ojos vendados). en el clásico tinyAVR)
La numeración de pines es extraña en los tinyAVR, y es culpa de Microchip: numeraron los pines dentro de los puertos de manera extraña: comienza en orden, excepto que PA0 es UPDI y generalmente no se puede utilizar, luego los pines de PORTB se numeran en orden inverso. luego PORTC vuelve a la misma numeración en sentido antihorario que PORTA. ¡Dame un respiro! Dado que la tradición es usar el pin 0 para el primer pin y que el último número sea el pin que no puede usar sin configurar un fusible que dificulte la programación del chip. Hubiera preferido poder numerarlos en sentido antihorario comenzando con A0 sin romper las convenciones no escritas del código Arduino. Se puede argumentar que tomé una mala decisión en las asignaciones de pines; tal vez deberían haber comenzado con PA0 (inutilizable a menos que se establezca un fusible, en cuyo caso el chip es difícil de programar) como pin 0, luego numerar los pines en sentido antihorario. Pero aún así no podrías hacer el tipo de trucos que harías si todos los puertos estuvieran en orden, a menos que numeraras los pines PORTB al revés. Si pudiera deshacerse de la expectativa de que todos los pines estén numerados en orden (y solo usen la notación PIN_Pxn), se podrían obtener ahorros significativos.
Predigo que dentro de 2 a 4 años habrá un AVR DA, DB, DD. Piezas de las series DU (el USB), EA y D/E/F reducidas a 8 (o al menos 14) y piezas de 64 pines con flash de 128k y el nuevo ADC. Y nada más con la marca ATtiny. Posiblemente la pregunta más importante que queda es si alguna vez reemplazarán el ATmega2560 con un AVR moderno con 100 pines en total (probablemente 80-88 de los cuales son E/S) y opciones de flash de hasta 256k; Eso presentaría tres problemas: primero, después de 56 pines de E/S no quedan más registros VPORT; el espacio de E/S bajo está lleno con 28 VPORT y 4 GPIOR. ¿Cómo manejarán los 4 puertos adicionales? (en el 2560, eran solo puertos de segunda clase a los que se accedía más lentamente y no tenían acceso de ciclo único. Tengo algunas reflexiones al respecto y la viabilidad con los pocos códigos de operación disponibles en el apéndice A aquí. Y en segundo lugar, violar la barrera de 128k en flash, debe ir a un contador de programa de 17 bits. Todos los saltos toman un ciclo adicional y todos los retornos toman un ciclo adicional. Finalmente, si se mantuvo la relación de RAM de AVR DB, esto. "D x parte a 256k de flash tendría 32k de RAM. Ahora recuerde cómo Progmem funciona en DX: no podrían llegar hasta 32. 24k Ram es definitivamente posible, tal vez incluso 28, pero a 32k, más 32k para Flash Mapped, no deja espacio para los SFR, que están en el mismo espacio de direcciones.
Vendo tableros de ruptura con regulador, encabezado Updi y encabezado en serie en mi tienda Tindie, así como en las tablas desnudas. Comprar en mi tienda ayuda a apoyar un mayor desarrollo en el núcleo, y es una excelente manera de comenzar a usar estas nuevas piezas emocionantes con Arduino. Actualmente están disponibles tableros Attiny1624, pero las piezas de 20 y 24 pines no se venderán como una placa ensamblada hasta que un diseño de PCB recientemente revisado regrese de la casa de la junta para habilitar el autoreset en el pasador de reembolso alternativo. También hay una revisión de la junta de 14 pines, pensó que es en gran medida cosmético. La máscara de soldadura amarilla tiene que irse, ya que la legibilidad parecía empeorar en los últimos lotes. Las nuevas placas también estandarizan un espacio de 0.6 "entre las filas de los pines, en lugar del espacio de 0.7" actual, por lo que podrá, por ejemplo, colocar el encabezado del pasador mecanizado sobre ellos y enchufarlos a un enchufe de inmersión ancha, o Úselos con nuestro tablero de creación de prototipos optimizado para ese espacio de fila. Los tableros de la Serie 0 ensamblados están siendo descontinuados y no se reabastecerán una vez que se agoten. Lo mismo sucederá para las piezas de la serie de 16k 2 una vez que las 32k estén disponibles.
El ADC en la serie 2 y la serie EA son los mejores ADC que se han lanzado en un AVR en la era moderna de AVR. Además de esos dos. Las comparaciones más cercanas son los AVR clásicos que obtuvieron ADC diferenciales con características de primer nivel (T841, Mega2560 y (sorprendentemente) el T861 es los competidores más fuertes). Si bien no es capaz de obtener una ganancia loca de 100x y 200x de la que algunas partes se jactaron en los clásicos días de AVR, nunca me quedó claro cuánto de lo que se estaba amplificando era simplemente ruido (considerando que mi experiencia admitida jugando con ADC diferenciales Voy a decir "probablemente la mayor parte, y definitivamente la mayor parte si me dejas diseñar el hardware, ¡no sé analógico!"). Este nuevo ADC es ciertamente altamente capaz, con una verdadera capacidad diferencial (a diferencia de la serie DA y DB), y uno que se eleva de cabeza y hombros por encima de cualquier cosa disponible en cualquier otra AVR moderna hasta la fecha. El amplificador de ganancia programable es una nueva capacidad, y queda por ver qué tipo de hazañas de medición analógica pueden obtener de ella; Ciertamente parece prometedor. Será especialmente interesante comprender las diferencias entre usar el PGA con ganancia 1x, frente a no usar el PGA y los beneficios y desventajas de hacerlo. (Microchip estaría bien servido por un documento que discutía cómo elegir la configuración ADC correcta para una tarea en el caso general; he planteado esta preocupación con Microchip y la persona con la que hablé indicaba que era una alta prioridad; La situación se ha mejorado enormemente, todavía parece que el grupo DOC recibió instrucciones específicas de no hacer ninguna recomendación concreta de ningún tipo.
La adición de la acumulación de 1024 muestras para los fines de sobremuestreo y decimación es una adición bienvenida, aunque también corre el riesgo de subestimar la magnitud y la relevancia del error de desplazamiento. (Tomar 1024 muestras, (todas las cuales tienen un error de desplazamiento dado), luego diezmar la suma para producir una medición ADC de 17 bits hace que sea fácil imaginar que cualquier error se limitaría a la pareja más baja de bits. Pero si el error fue, digamos 5 LSB en una sola medición, cuando acumula 1024 muestras y diezpas, tiene un error de compensación de 160, es extremadamente fácil ver eso y pensar que es una señal no ruido.
El primer chip de tamaño completo (no pequeño) con el nuevo ADC está disponible en paquetes de 28-48 pines con flash de hasta 64k. Hubo la especulación habitual sobre qué si algo cambiaría de 2 series a la serie EA: parece que la respuesta es, se eliminó una de las perillas confusas, y se cortó el letrero automático para las mediciones acumuladas ((
El temporizador Tipo D solo se usa para PWM en las piezas de la serie 1 de Pin 1 de 20/24 en la configuración predeterminada del PIN PWM. En las partes más pequeñas, no nos permitiría aumentar el número total de pines PWM. Solo los pines WOC y WOD (en PC0 y PC1 respectivamente) ya no tienen PWM dirigido por TCA. Como tal, dado que AnalogWrite () no admite ninguna característica que se habilite desactivando el modo dividido (como PWM de 16 bits) o mejorado mediante el uso del temporizador Tipo D (como ajustar la frecuencia), sería peor, porque sería peor, porque Requeriría espacio adicional para almacenar la rutina para encender y apagar PWM de dos tipos de temporizador, en lugar de uno. Esto no es insignificante en las partes flash más pequeñas; Está del orden de 600 bytes. 150 para DigitalWrite () y 450 para AnalogWrite () si alguna vez se llaman en un pin TCD PWM. El optimizador debería poder optimizar esa parte de esas funciones en este caso, siempre que los pines utilizados con esas funciones no incluyan ningún pines TCD PWM. Tenga en cuenta que el optimizador los considerará de forma independiente, es decir, DigitalWrite () incluirá el código para apagar TCD PWM si se usa con un PIN que usa TCD para PWM, ya sea que alguna vez llame o no AnalogWrite () en ese pin.
A diferencia de casi todos los demás AVR (puedo pensar en quizás 3 ejemplos, y solo uno de ellos es un "bono" no un "unbonus"), hay características adicionales de "bonificación" basadas en el tamaño flash de una familia . Las versiones de 16k y 32k (solo) tienen algunas características adicionales (que tampoco parecen haber sido consideradas para el precio): todas tienen 2K de RAM, ya sea 16k o 32k, tienen 3 comparadores analógicos (incluido un modo de ventana Opción), un segundo, necesarios desesperadamente, un temporizador Tipo B, y más extraño de todo, tienen un segundo ADC, ¡que difiere solo en el que corresponden los canales!
A diferencia de los AVR clásicos, en estas partes, el flash se asigna al mismo espacio de direcciones que el resto de la memoria . Esto significa que pgm_read_*_near()
no es necesario para leer directamente desde Flash. Debido a esto, el compilador coloca automáticamente cualquier variable declarada const
en progmem, y lo accede de manera apropiada; ya no necesita declararlos explícitamente como progmem. Esto incluye literales de cadena citados, por lo que la macro f () ya no es necesaria, aunque para mantener la compatibilidad con algunas bibliotecas de terceros, f () todavía declara su argumento progmem.
Sin embargo, tenga en cuenta que si declara explícitamente un progmem variable, aún debe usar las funciones pgm_read
para leerlo, al igual que en los AVR clásicos. Cuando se declara una variable progmem en piezas con flash mapeado de memoria, el puntero se compensa (la dirección es relativa al inicio de flash, no el inicio del espacio de direcciones); Este mismo desplazamiento se aplica cuando se usa pgm_read_*_near()
macros. Tenga en cuenta que declarar las cosas progmem y acceder con pgm_read_*_near
las funciones, aunque funciona bien, es más lento y desperdicia una pequeña cantidad de flash (en comparación con simplemente declarar las variables const); Lo mismo ocurre con la macro f () con cadenas constantes en 2.1.0 y más tarde (durante un período de tiempo antes de 2.1.0, F()
no hizo nada, pero eso causó problemas para las bibliotecas de terceros). Los autores sostuvieron que el problema era con el núcleo, no con la biblioteca, y mi elección era aceptar menos eficiencia o negar el acceso a mis usuarios a bibliotecas populares). El uso de la macro F()
puede ser necesaria para la compatibilidad con algunas bibliotecas de terceros (los casos específicos que forzaron el retorno de F()
sobre nosotros no eran de ese tipo; en realidad pudimos hacer que los que conocía trabajara con el F ()-Código AS-Noop, y tomaron algunos bytes menos flash como resultado).
Las versiones automotrices también deberían funcionar. Siempre debe seleccionar las velocidades de reloj derivadas de 16 MHz en estas partes. No admiten una operación de 20 MHz, y las opciones de reloj sintonizadas no deben usarse.
Ahora, a la buena parte, donde podemos hablar sobre cómo todo esto está expuesto por Megatinycore. Comenzaremos con la cuestión de cómo debe consultar los pines para obtener los mejores resultados, y luego pasar a las características centrales, las opciones de menú, antes de terminar con una serie de enlaces a documentos con más detalles en varios subsistemas.
La simple cuestión de cómo referirse a un PIN para Analogread () y DigitalRead (), particularmente en hardware no estándar, ha sido una fuente persistente de confusión entre los usuarios de Arduino. Es mi opinión que gran parte de la culpa recae en las decisiones tomadas por el equipo de Arduino (y el autor de Cableado ante ellos) con respecto a cómo se refería los pines; La designación de algunos pines como "pines analógicos" lleva a las personas a pensar que esos pines no se pueden usar para las operaciones digitales (se consideran mejor como "pines con entrada analógica", como cómo hay "pines que pueden emitir PWM"). El hecho de que los alfileres se hayan renumerado tradicionalmente ha enturbiado aún más el agua. Para las piezas AVR clásicas no estándar, las asuntos a menudo empeoran aún más por múltiples "mapeaciones de pines" incompatibles creadas por varios autores a lo largo de los años para hacer que la parte actúe "más como una Uno" o para algún otro propósito (Attinycore es un particular Mess de esta manera, con algunas partes que tienen tres asignaciones de pines completamente diferentes, en al menos un caso, una de las asignaciones alternativas es un trabajo inspirado en el diablo de puro mal, que requiere nada menos que una tabla de búsqueda adicional para convertir pines analógicos en digital digital alfileres).
Este núcleo utiliza un esquema simple para asignar los números de pin de Arduino: los pines están numerados a partir del pin de E/S más cercano a VCC como PIN 0 y procediendo en sentido antihorario, omitiendo el PIN (en su mayoría) no utilizado. El PIN UPDI se asigna al último número de PIN (como se señaló anteriormente, es posible leer el PIN UPDI (las lecturas analógicas y digitales funcionan) incluso si no se establece como GPIO). Recomendamos esto como último recurso: el pin updi siempre tiene su pullup habilitada cuando no está configurado como un pin GPIO, y una señal que se parece demasiado a la secuencia de habilitación de actualización causará una operación no deseada.
Para evitar toda confusión sobre las identidades de PIN y eliminar la ambigüedad, recomendamos usar la notación PIN_PXN para referirse a PIN a menos que esté utilizando un tablero de desarrollo con diferentes números o nombres para los pines impresos en él. Esto maximizará la portabilidad de su código a otro hardware similar y facilitará la búsqueda de información sobre los pines que está utilizando en las hojas de datos relevantes, si eso es necesario.
Esta es la forma recomendada de referirse a los pines #defines
también se proporciona de la forma PIN_Pxn
, donde x
es A, B o C, y n
es un número 0-7 - (no debe confundirse con el PIN_AN define a continuación). Estos simplemente se resuelven al número de PIN digital del PIN en cuestión: no pasan por una ruta de código diferente ni nada. Sin embargo, tienen una utilidad particular en el código de escritura que funciona en la línea de productos con periféricos que están vinculados a ciertos pines (por puerto), como lo son la mayoría de los periféricos. Varias piezas de código de demostración en la documentación aprovechan esto. También es posible la manipulación directa de puertos, y de hecho, hay varias opciones adicionales poderosas disponibles para ella, consulte la manipulación de puertos directos .
PIN_Pxn
- no Pxn
, y no PIN_xn
- ¡Esas significan cosas diferentes!
Cuando se usa un solo número para referirse a un PIN, en la documentación o en su código, siempre es el "número de pin Arduino". Estos son los números de PIN que se muestran en naranja (para pines capaces de anicogroad ()) y azul (para pines que no lo están) en los gráficos de pinout. Todas las otras formas de referencia a pines están #definidas al número de pin Arduino correspondiente.
El núcleo también proporciona An
y PIN_An
(donde n
es un número de 0 a 11). Al igual que con el núcleo oficial, PIN_An
se define como el número de PIN digital del PIN compartido con el canal analógico N, se refieren a los números del canal ADC0. Este sistema de nombres es similar a lo que se usó en muchos núcleos AVR clásicos , pero aquí, solo están #definidos como el número de pin Arduino correspondiente . Si necesita obtener el número de canal analógico en un PIN digital, use digitalPinToAnalogInput(pin)
Macro, pero solo necesita eso si está escribiendo una biblioteca ADC avanzada.
Estas partes (bueno, al menos la serie 1/2, la serie 0 se entendía como una opción de presupuesto, excepto que no pudieron reducir el presupuesto, y solo son un par de centavos más baratos) proporcionan una excelente caja de herramientas de versátil y poderosos periféricos; Los mejores están a la par o mejor que las piezas megaavr clásicas, por un precio TinyAVR. Uno de los principios rectores del diseño de Megatinycore, como con mis otros núcleos, es permitir que las piezas compatibles alcancen su máximo potencial, o lo más cerca posible de las limitaciones de Arduino. Esta sección (muy grande) cubre las características de estas piezas y cómo están expuestas por MegatinyCore, así como características del núcleo en sí. Esta sección (muy grande) intenta cubrir cada una de las áreas de características. ¡Trate de encontrar la función con la que está trabajando si está intentando usar alguna función de chip y tener problemas!
No hacemos afirmaciones sobre los rangos de voltaje o temperatura para las piezas overclocadas; todo lo que reclamamos es que al menos una de las chips que hemos trabajado a esa velocidad a temperatura ambiente, ejecutando un boceto específico, a 5V. Se espera que su kilometraje varíe, pero generalmente será mejor con una especificación F versus una parte de especificación N o U.
IMPORTANTE: ¡lea sobre el ajuste antes de seleccionar cualquier opción sintonizada!
Puede encontrar más información sobre estas velocidades de reloj en la referencia del reloj
Los voltajes que se muestran son aquellos garantizados para funcionar por las especificaciones del fabricante (a menos que empujen los límites del rango de temperatura de funcionamiento, estas piezas generalmente lo harán mucho mejor (la serie 2 generalmente funcionan a 32 MHz y 5V @ temperatura ambiente incluso desde el oscilador interno; el 0 /La serie 1 también generalmente funcionará a 32 MHz con reloj externo siempre que la fuente de alimentación sea un establo de 5.0-5.5V).
No se requiere acción para establecer el fusible OSCCFG
cuando el boceto se cargue a través de Updi. Cuando se sube a través de Optiboot, el fusible no se puede cambiar, por lo que lo que se eligió cuando se quemó el cargador de arranque es lo que se usa, y solo "quemar el gestor de arranque" o cargar un boceto a través de Updi cambiará eso.
Todas las opciones de velocidad de reloj del oscilador interno usan la calibración predeterminada de fábrica a menos que se seleccione una opción "sintonizada", en cuyo caso la calibración se ajusta como se documenta en la referencia de sintonización . Esto se puede usar para obtener una operación de 16 MHz en un chip Optiboot fusionado por 20 MHz y viceversa.
Consulte la referencia de calificación de velocidad para obtener más información sobre las calificaciones de velocidad del fabricante. Tenga en cuenta que esos son los voltajes y las velocidades del reloj a las que se garantiza que funcione. Estas piezas están destinadas a ser adecuadas para su uso en aplicaciones donde una falla inesperada de alguna descripción podría representar un peligro para personas o propiedades (piense en automóviles, equipos industriales, aviones, reactores nucleares, lugares donde las personas podían morir si la parte no funcionaba) y yo Cree también para aplicaciones militares, que tienen requisitos de confiabilidad similares, solo por la razón opuesta. Los usuarios típicos de pasatiempos estarán mucho más relajados sobre el potencial de problemas de estabilidad, y los accidentes son poco más que una molestia, y los extremos de las piezas de rango de temperatura extendido están mucho más allá de lo que necesitaríamos. Suponiendo que el tablero tenía un recubrimiento impermeable, térmicamente, una parte de grado N debería poder funcionar según el grado de velocidad en una olla de agua hirviendo. Y eso es solo el N-Spec. ¡El F-Spec debería ser bueno para 125!
Se ha establecido que las piezas de temperatura extendidas se overcloce mejor, lo que tiene sentido. Se espera que una parte que se especifica para que se ejecute a 20 MHz a 125 ° C tenga una mejor oportunidad de correr a 32 MHz a temperatura ambiente que una especificada solo para correr a 20 MHz a 105 ° C
A partir de la versión 2.4.0, ahora proporcionamos una opción "Junta de microchip oficial". Esto no hace nada especial que no sea definir LED_BUILTIN
para que sea el pin que tiene el LED en esa placa, en lugar de A7, y definir una macro PIN_BUTTON_BUILTIN
definida como el pin con el botón de usuario y hacer "cargar" con el no no -optiboot versión siempre use el programador/depurador integrado; Herramientas -> El programador se utilizará solo para "Burn Bootloader" y "Cargar usando programador". En el caso del Attiny416 XPlained Nano, también selecciona la versión del gestor de arranque que usa los pines alternativos para el puerto serie: no usa automáticamente los pines alternativos para USART0 como si hubiera hecho Serial.swap (1) todavía - La funcionalidad para admitir el intercambio predeterminado de los pines en serie vendrá en una actualización futura, junto con algunos otros cambios en la maquinaria subyacente al mecanismo de fielps que, con suerte, también reducirá el uso de flash.
Como se señaló anteriormente, pueden no funcionar correctamente en plataformas Linux de 32 bits. Esto está más allá de mi control; No construyo binarios de avrdude y no estoy asumiendo esa tarea tampoco. Ya tengo demasiados.
blink()
toma más flash en el XPlained Mini frente al XPlained Pro?¡Ambos tienen el mismo Attiny817! ¿Cómo pueden ser diferentes?
Por la misma razón que Blink tomará más flash si lo cambia para usar PIN_PC0
en lugar de PIN_PB4
: PC0, utilizado en el mini XPlained es un pin PWM, mientras que PB4, utilizado por el Pro Pro no lo es. Dado que ese es el único PIN en el que se está utilizando DigitalWrite (), el compilador es libre de optimizar cualquier cosa que no sea necesaria para DigitalWrite () en ese pin, incluida la funcionalidad para desactivar la salida de PWM en un PIN que admite PWM . La diferencia se desvanece si DigitalWrite () también se usa en un pin que admite PWM en ambos dispositivos (lo que resulta en el resultado de uso de flash más alto) o si DigitalWrite () se reemplaza con DigitalWriteFast (), que usará menos flash (pero supone que ganó que ganó 'T Llámalo en un pin de salida PWM).
Cada vez que se usa un programador UPDI para cargar código, todos los fusibles que se pueden establecer "de forma segura" (como, sin riesgo de bloquear la placa, o bloquear el tablero si uno no tiene acceso a un programador de HV), y que tienen alguno Se establecerán opciones de configuración incorporadas. Por lo tanto, excepto cuando se indique, el comportamiento siempre coincidirá con el menú de herramientas seleccionadas. En resumen, estos se manejan de la siguiente manera:
WDTCFG will not be changed - it is not configured by megaTinyCore except to reset it to the factory default when doing "burn bootloader".
BODCFG will not be changed - not safe, you could set the BOD level to 4.3 on a 3.3v system, and then it would need to get > 4.3v applied to reprogram it. If it is on the same circuit board as parts that would be damaged, this is a difficult situation to recover from.
OSCCFG will be set
TCD0CFG will not be changed - it is not configured by megaTinyCore except to reset it to the factory default when doing "burn bootloader".
SYSCFG0 will not be changed - not safe
SYSCFG1 will be set
APPEND will not be changed - it is not configured by megaTinyCore. There is insufficient demand to justify the development effort.to make use of this as DxCore does
BOOTEND will be set
LOCKBIT will not be changed - it is not configured by megaTinyCore; supporting the lockbits presents several additional complications, and commercial users with need of this facility are unlikely to be using the Arduino IDE to program production units.
BODCFG
no es seguro, porque establecer esto en un voltaje más alto que el tablero se ejecuta y habilitarlo "lade" la placa hasta que se pueda suministrar un voltaje de funcionamiento más alto; Esto podría ser particularmente incómodo si se suelde a la misma PCB que los dispositivos que no tolerarán esos voltajes.
SYSCFG0
no es seguro porque aquí es donde vive RSTPINCFG
; Cambiar esto puede dejar la placa improvisable, excepto a través de la programación HV Updi, y no todos tienen un programador HV Updi. En el futuro si/cuando un programador que garantiza la capacidad de HV Updi que se puede seleccionar como programador (es decir, es posible hacer una opción de herramientas -> programador que solo funcionará con programadores de HV) Este fusible se establecerá automáticamente cuando se use ese programador.
Como resultado , en 2.2.0 y posterior, ya no necesita 'quemar el cargador de arranque' para cambiar entre velocidades derivadas de 16 MHz y 20 MHz derivadas al cargar usando Updi
Este núcleo siempre usa la optimización del tiempo de enlace para reducir el uso de flash: todas las versiones del compilador que admiten las piezas de la serie TinyAVR 0/1/2 también admiten LTO, por lo que no hay necesidad de hacerlo opcional, como se hizo con AttinyCore. Esta fue una gran mejora en Codesize cuando se introduce, ¡generalmente en el orden del 5-20%!
Todas estas piezas tienen una gran cantidad de entradas analógicas: la serie DA y DB tienen hasta 22 entradas analógicas, mientras que la serie DD tiene entrada analógica en cada pin que no se usa para conducir el cristal HF (aunque los pines en PORTC son Solo admitido cuando MVIO está apagado). Se pueden leer con analogRead()
como en un AVR normal, y nos quedamos de forma predeterminada a una resolución de 10 bits; Puede cambiar a los 12 bits completos con analogReadResolution()
, y usar las funciones de Analogread mejoradas para tomar lecturas diezpeadas y de muestras automáticas para una mayor resolución y tomar mediciones diferenciales. Hay 4 referencias de voltaje interno en 1.024, 2.048, 4.096 y 2.5V, más soporte para el voltaje de referencia externo (y VDD, por supuesto). Las lecturas de ADC se toman 3 veces más rápido que un AVR clásico, y esa velocidad se puede duplicar nuevamente si lo que está midiendo es de baja impedancia o extender el tiempo de muestreo por un factor en gran medida para leer fuentes de impedancia muy alta. Esto se detalla en la referencia analógica.
Las piezas de la serie DX tienen un DAC de 10 bits que puede generar un voltaje analógico real (tenga en cuenta que esto proporciona baja corriente y solo puede usarse como una referencia de voltaje o un voltaje de control, no se puede usar para alimentar otros dispositivos). Esto genera voltajes entre 0 y el VREF
seleccionado (a diferencia de la Serie TinyAVR 1, ¡esto puede ser VCC!). Establezca el voltaje de referencia DAC a través de la función DACR reference()
: pase cualquiera de las opciones de referencia ADC enumeradas en la sección ADC anterior (¡incluido VDD!). Llame analogWrite()
en el pin DAC (PD6) para establecer el voltaje que el DAC lo emite (esto lo usa en modo de 8 bits). Para apagar la salida DAC, llame a digitalWrite()
o turnOffPWM()
en ese pin.
Puede haber opciones adicionales para configurar el DAC en la serie EA.
Vea la referencia ADC y DAC para obtener todos los detalles.
El uso de las constantes An
para pines analógicos está en desuso: la práctica recomendada es simplemente usar el número de PIN digital, o mejor aún, usar notación PIN_Pxn
al llamar analogRead()
.
Hay más opciones que en AVR clásico para restablecer, incluso si el código se cuelga de alguna manera. El temporizador Watchdog solo puede restablecer (usar el RTC y el PIT para interrupciones cronometradas).
Vea la referencia de restablecimiento y vigilancia (WDT) y la biblioteca núcleo auxiliar Megatinycore
Este núcleo agrega una serie de nuevas características que incluyen E/S digital rápida (1-14 relojes dependiendo de lo que se sabe en el tiempo de compilación, y 2-28 bytes de flash (el número de pin debe ser conocido en el tiempo de compilación para las funciones ________Fast()
, y para configurar todos los ajustes por pin el hardware que tiene con pinConfigure()
.
Vea la referencia mejorada de E/S digital .
Todas las piezas de la serie 0/1 tienen un solo puerto serie de hardware (UART o USART); Las partes de la serie 2 tienen dos. Funciona exactamente como el de las tablas oficiales de Arduino, excepto que no hay un reseto automático, a menos que lo haya conectado fusionando el pin de actualización como restablecimiento (requiriendo HV-UPDI o el cargador de arranque Optiboot para cargar el código) o establecer Up un "Pin de reinicio ersatz" como se describe en otra parte de este documento. Vea los gráficos de pinos para las ubicaciones de los alfileres en serie.
Antes de poner la pieza en un modo de suspensión, o de otra manera deshabilitar su capacidad para transmitir, asegúrese de que haya terminado de enviar los datos en el búfer llamando a Serial.flush()
, de lo contrario, el puerto serie emitirá caracteres corruptos y/o fallará Para completar la transmisión de un mensaje.
Vea la referencia en serie para obtener una lista completa de opciones. A partir de 2.5.0, es compatible con casi todos los tipos de funcionalidad que puede hacer el hardware en serie, incluido el modo RS485, medio-dúplex (a través de LBME y ODME), e incluso el modo SPI sincrónico y maestro, y 2.6.0 agregará autolaud, Aunque no es muy útil.
Todas estas piezas tienen un solo periférico SPI de hardware. Funciona como el de los tableros oficiales de Arduino usando la biblioteca SPI.H. Vea los gráficos de Pinout para la ubicación de estos alfileres. En las partes de 8 pines, la única opción para el pin SS es PA0 (el pin actualizador/reiniciado); Sin embargo, esto no importa a los fines de este núcleo, porque, como la biblioteca oficial, esto solo funciona como maestro, y el pin SS se usa solo cuando actúa potencialmente como esclavo.
En todas las partes, excepto las partes de 14 pines, los pines SPI se pueden mover a una ubicación alternativa (nota: en partes de 8 pines, el pin SCK no se puede mover). Esto se configura utilizando los métodos SPI.swap()
o SPI.pins()
. Ambos logran lo mismo, pero difieren en cómo especifica el conjunto de pines a usar. Esto debe llamarse antes de llamar SPI.begin()
.
SPI.swap(1)
o SPI.swap(0)
establecerá la asignación en las pines alternativas ( 1
) o predeterminadas ( 0
). Devolverá verdadero si esta es una opción válida y falsa si no es así (no necesita verificar esto, pero puede ser útil durante el desarrollo). Si se especifica una opción no válida, se establecerá en la predeterminada.
SPI.pins(MOSI pin, MISO pin, SCK pin, SS pin);
- Esto establecerá el mapeo en cualquier mapeo que tenga los pines especificados. Si esta no es una opción de mapeo válida, devolverá False y establecerá la asignación en el valor predeterminado. Esto usa más flash que SPI.swap()
para que se prefiera el método. El argumento SS pin
es opcional, ya que el PIN no se usa cuando actúa como un maestro SPI, y ni esta biblioteca ni el soporte oficial de la biblioteca SPI.H actúan como esclavo.
Cuando se puede determinar que los argumentos pasados a SPI.swap()
o SPI.pins()
no son válidos en el momento de la compilación (más comúnmente cuando los argumentos son constantes, que casi siempre son), el núcleo generará una compilación error a ese efecto. Esto está destinado a ayudar a evitar que tales problemas detectables requieran tiempo de depuración en el hardware.
Este núcleo desactiva el pin SS, lo que significa que el pin "SS" se puede usar para el propósito que desee, y el PIN es relevante solo al hacer un esclavo SPI (lo que requiere que implemente la interacción con el periférico SPI, aunque no es ciencia espacial o cualquier cosa). En el clásico AVRS, si SS fuera una entrada y SPI estaba habilitado, estaba actuando como el pin SS, y si se bajara, cambiaría el dispositivo al modo esclavo (y SPI.H no funcionaría hasta que volviera a volver a ser maestro modo, que no se realizó automáticamente).
Todas estas piezas tienen un solo periférico de hardware I2C (TWI). Presenta una API compatible con la implementación estándar de Arduino, pero con soporte adicional para múltiples direcciones de esclavos, respondiendo direcciones de llamadas generales y, más emocionantemente, ¡una operación simultánea de maestría y esclavo! (Nuevo en 2.5.0).
Consulte la documentación de Wire.H para obtener una descripción y detalles completos. El hardware I2C es uno de los periféricos más complicados. Wire ha tenido muchas nuevas mejoras calientes recientemente.
El núcleo proporciona hardware PWM a través de la función estándar analogWrite()
. En las partes de 8 pines (412, 212, 402, 204), están disponibles 4 pines PWM. En todas las demás partes, excepto las piezas de la serie 1 con 20 o 24 pines, hay 6 pines PWM disponibles, todos impulsados por el temporizador A (TCA0). Las piezas de la serie de 20 y 24 pines 1 tienen dos pines adicionales, impulsadas por TCD0. Aparentemente, la serie 2 intercambiaron TCD0 por un segundo puerto serie y un ADC de súper probabilidad, esas partes también tienen 6 pines PWM. Los temporizadores Tipo B (TCBN) no se pueden usar para pines PWM adicionales: sus pines de salida son los mismos que los disponibles con el temporizador A y a menudo son demasiado útiles para justificar el uso de un TCB completo para. Sin embargo, puede tomarlos si necesita generar PWM a diferentes frecuencias, aunque el hecho de que el preescalador no pueda diferir de los límites del temporizador Tipo A también. Vea los gráficos de Pinout para obtener una lista de las cuales los pines admiten PWM.
A partir de 2.6.8, se agregó un submenú de herramientas para permitirle elegir entre las asignaciones PWM plausiblemente útiles, y (en la serie 1) para deshabilitar el TCD PWM para guardar Flash.
Tenga en cuenta que TCA0 (el temporizador Tipo A) en todas las partes está configurado por el núcleo al inicio para operar en modo dividido para admitir la mayoría de los pines PWM posibles con analogWrite()
. A partir de las versiones 2.2.x, se ha agregado una función takeOverTCA0()
, que se puede llamar para instruir al núcleo no escribir a los registros TCA0 ni asumir ningún modo o comportamiento particular para TCA0. analogWrite()
no generará PWM, excepto en pines impulsados por TCD0 en las partes de 20/24 pines ni digitalWrite()
lo apagará si desea reconfigurar TCA0 para otros fines, consulte la guía a continuación y el "reinicio duro" El temporizador de regreso a la configuración de stock.
El 3216, 1616, 816, 416 y el 3217, 1617 y 817 tienen dos pines PWM adicionales impulsados por el temporizador D (PC0 y PC1 - Pins 10 y 11 en X16, 12 y 13 en X17). El temporizador D es un temporizador asincrónico (async), y las salidas no se pueden habilitar o deshabilitar sin detener brevemente el temporizador. Esto da como resultado una breve falla en el otro pasador PWM (si actualmente está saliendo PWM) y hacerlo requiere un poco más tiempo, aunque la duración de esta falla es inferior a 1 US. If TCD is used as the millis timer - which is the default on any part that has a type D timer (in order to keep the timers that are more readily repurposed available - TCD0 is not an easy peripheral to work with), this will result in millis()
losing a very small amount of time (under 1 us) every time PWM is turned on or off on a TCD pin.
As of 2.2.0, analogWrite()
of 0 or 255 on a TCD-driven PWM pin does not disconnect the pin from the timer - instead it results in a constant HIGH
or LOW
output without disconnecting the timer (use digitalWrite()
for that ). This means that analogWrite(PIN_PC0, 0)
or analogWrite(PIN_PC1, 0)
can be used to connect the timer to the pin without outputting PWM (yet) - doing this on both pins prior to setting any other duty cycles would allow one to ensure that no glitch of any sort occurs on the other TCD0 pin when the second pin is connected to it. Only digitalWrite()
or turnOffPWM()
will disconnect the timer from the pin . When outputting a HIGH
in this way, the pin is "inverted"; this means that digitalRead()
on it will return 0, not 1 (if you're digitalRead()
'ing a pin, which you have set to output a constant HIGH
, using analogWrite()
, and it's one of those two pins, it will read LOW
. However, if you are using digitalRead()
on a pin that you've set to output a constant value, you may be doing something wrong in general.
Because TCD is async, and can run from the unprescaled internal oscillator, that means you can lower the system clock frequency without affecting the speed of the PWM. While there is a difference in PWM frequency between 16-MHz derived and 20-MHz derived clocks, there is no change in frequency for different system clock speeds for the TCD-controlled pins (the TCA-controlled pins will vary by a factor of two) The exception to this is when TCD0 is used as the millis/micros timing source at 1 MHz - running at full speed there resulted in spending an unreasonable fraction of runtime in the millis()
ISR (tens of percent of the tiempo).
TCD0 is used for millis()
/ micros()
by default on parts that have it. Be aware that this does have a small flash penalty, so you can save flash by switching to use TCA or a TCB as the timer. That will also make micros()
return faster. There is a shortage of timers on most of these parts, and I have not seen anyone talking about or posting code that reconfigures the TCD. Meanwhile everyone seems to be reconfiguring the TCA and many libraries need a TCB. These factors have been the impetus for making TCD0 the default for millis()
/ micros()
: it is least likely to directly interfere.
On some versions of megaTinyCore prior to 2.2.0, PWM on the TCD0 pins was entirely broken.
For general information on the available timers and how they are used PWM and other functions, consult the guide: This also covers the PWM frequencies that these timers will give you at various system clocks. Timers and megaTinyCore
Support for tone()
is provided on all parts using TCB0, unless TCB1 is present and TCB0 is set as millis()
source. This is like the standard tone()
function. Unlike on some classic AVRs, it does not support use of the hardware 'output compare' to generate tones; due to the very limited PWM capabilities and restricted prescaler selection for the TCB timers, this is not practical. See caveats below if using TCB0 or TCB1 for millis()
/ micros()
settings. See the timer reference for more information
tone()
can only play a tone on one pin at a time. In theory you can play one tone per Type B timer, simultaneously, without anything more exotic than what tone()
does now other than adding a capability to manage the multiple pins. It is my opinion that those belong in a library, not the core. See comments in tone.cpp
for some thoughts if you want to implement something like that - I'd be happy to give more thoughts if you have questions.
megaTinyCore provides the option to use any available timer on a part for the millis()
/ micros()
timekeeping, controlled by a Tools submenu. It can be disabled entirely if needed to save flash, allow use of all timer interrupts or eliminate the periodic background interrupt. By default, TCD0 will be used by on parts that have one - otherwise TCA0 will be used (in versions prior to 1.1.9, TCA0 was used by default on parts that could output PWM with TCD0 on pins not available for TCA0 PWM). All timers available on the parts can be used: TCA0, TCD0 (on parts that have it), TCB0, TCB1 (where present) and the RTC. Many of these - particularly the non-default options, involve tradeoffs. In brief, TCA0 is a very versatile timer that users often want to reconfigure, TCD0 loses a small amount of time when PWM is turned on or off on the two TCD0 PWM pins (10,11 on 20-pin parts, 12,13 on 24-pin parts), TCB0 conflicts with Servo
and tone()
on parts that don't have TCB1, and when the RTC is used micros()
is not available at all because the clock isn't fast enough. With these limitations in mind, the timer selection menu provides a way to move millis()
/ micros()
to the timer most appropriate for your needs.
For more information, on the hardware timers of the supported parts, and how they are used by megaTinyCore's built-in functionality, see the Timers and megaTinyCore Reference .
2.3.0 fixed a long-standing (though surprisingly low impact) "time travel" bug.
millis()
If the RTC is selected as the timer for millis()
timekeeping, micros()
will not be available. Additionally, this timer will be configured to run while in STANDBY sleep mode. This has two important consequences: First, it will keep time while in sleep. Secondly, every 64 seconds, the RTC overflow interrupt will fire, waking the chip - thus, if you are using the RTC for millis()
and putting the part into sleep, you should declare a volatile global variable that you set in the ISR that is supposed to wake the part, eg volatile boolean ShouldWakeUp=0;
, set it to 1 in the ISR, and when you put the ATtiny to sleep, have it check this immediately after waking, going back to sleep if it's not set, and clearing it if it is set, eg:
void GoToSleep () {
do {
sleep_cpu ();
} while (!ShouldWakeUp)
ShouldWakeUp= 0 ;
}
This functionality will be made easier to use via ModernSleep when that library is available.
This board package also supports using an external 32.768khz crystal as the clock source for the RTC (not supported on 0-Series or 8-pin parts - not our fault, the hardware doesn't support it). If this is used, make sure that the crystal is connected between the TOSC1 and TOSC2 pins (these are the same as the TX and RX pins with the default pin mapping - very convenient right?), that nothing else is, that no excessively long wires or traces are connected to these pins, and that appropriate loading capacitors per crystal manufacturer datasheet are connected (and that it's not a full moon - I found the 32k crystal to be extremely uncooperative. To reduce power usage, they try to drive the crystal as weakly as they can get away with, which in turn makes it more susceptible to interference.
Yes, you can use an external oscillator for the RTC, at least on 1 and 2 series parts. When it's an oscillator not a crystal, it can be fed to either TOSC0 or EXTCLK; better support for this will come in the future. Note that while TOSC0 won't let you run the RTC at widlly faster speeds. EXTCLK will.
printf()
Support for "printable" Class Unlike the official board packages, but like many third party board packages, megaTinyCore includes the printf()
method for the printable class (used for UART serial ports and most everything else with print()
methods); this works like sprintf()
, except that it outputs to the device in question; Por ejemplo:
Serial.printf( " Milliseconds since start: %ld n " , millis());
Note that using this method will pull in just as much bloat as sprintf()
and is subject to the same limitations as printf - by default, floating point values aren't printed. You can use this with all serial ports You can choose to have a full printf()
implementation from a Tools submenu if you want to print floating point numbers, at a cost of some additional flash.
printf()
and Variants Thereof Have Many Pitfalls There are a considerable number of ways to screw up with printf()
. Some of the recent issues that have come up:
printf()
- printf()
bugs are a common cause of software bugs in the real world. Be aware that while you can use F() on the format string, there are no warnings for invalid format strings in that case ; a conservative programmer would first make the app work without F() around the format string, and only switch to F() once the format string was known working.From cplusplus.com:
The length sub-specifier modifies the length of the data type. This is a chart showing the types used to interpret the corresponding arguments with and without length specifier
(if a different type is used, the proper type promotion or conversion is performed, if allowed): Strikethrough mine 'cause that don't work here (and it's not my fault nor under my control - it's supplied with avrlibc, and I suspect that it's because the overhead of implementing it on an 8-bit AVR is too large). When incorrect length specifiers are given (including none when one should be used) surprising things happen. It looks to me like all the arguments get smushed together into a group of bytes. Then it reads the format string, and when it gets to a format specifier for an N byte datatype, it grabs N bytes from the argument array, formats them and prints them to whatever you're printing to, proceeding until the end of the format cadena. Thus, failing to match the format specifiers' length modifiers with the arguments will result in printing wrong data, for that substitution and all subsequent ones in that call toprintf()
.
The table below comprises the relevant lines from that table - many standard types are not a thing in Arduino (their original was several times longer, but including that mess would just complicate this discussion.
longitud | di | uox X | f F e E g G a A | do | s | pag | norte |
---|---|---|---|---|---|---|---|
(ninguno) | int16 | uint16 | flotar | entero | carbonizarse* | vacío* | int* |
S.S | int8 | uint8 | carbonizarse* | ||||
yo | int32 | uint32 | int32_t* |
Notice that there is no line for 64 bit types in the table above; these are not supported (support for 64-bit types is pretty spotty, which is not surprising. Variables of that size are hard to work with on an 8-bit microcontroller with just 32 working registers), and using uint64's is something you should try to avoid, similar to driving on the wrong side of the road, flying kites during thunder storms, or drinking bleach. While all have been suggested (Europe is really persistent about the side of the road; As far as I'm concerned, it comes down to physics; mirror image symmetry i. This applies to all versions of printf()
- the capability is not supplied by avr-libc.
There are reports of memory corruption with printf, I suspect it is misunderstanding of above that is actually at hand here.
printf()
Implementation A Tools submenu lets you choose from three levels of printf()
: full printf()
with all features, the default one that drops float support to save 1k of flash, and the minimal one drops almost everything and for another 450 bytes flash saving (will be a big deal on the 16k and 8k parts. Less so on 128k ones). Note that selecting any non-default option here will cause it to be included in the binary even if it's never called - and if it's never called, it normally wouldn't be included. So an empty sketch will take more space with minimal printf()
selected than with the default, while a sketch that uses printf()
will take less space with minimal printf()
vs default.
Entonces:
Menu selection | printf() or similar used? | Arriba |
---|---|---|
Por defecto | No | 0 by definition |
Por defecto | Sí | apx 1500 |
Mínimo | No | apx 1000 |
Mínimo | Sí | apx 1100 |
Lleno | No | apx 2800 |
Lleno | Sí | apx 3000 |
Notice how when not using printf or similar functions, you are far better off leaving it on the default, as opposed to switching to minimal thinking you'll save flash, because you you'll use more flash not less.
All pins can be used with attachInterrupt()
and detachInterrupt()
, on RISING
, FALLING
, CHANGE
, or LOW
. All pins can wake the chip from sleep on CHANGE
or LOW
. Pins marked as Async Interrupt pins on the megaTinyCore pinout charts (pins 2 and 6 within each port) can be used to wake from sleep on RISING
and FALLING
edges as well. Those pins are termed "fully asynchronous pins" in the datasheet.
Advanced users can instead set up interrupts manually, ignoring attachInterrupt()
, manipulating the relevant port registers appropriately and defining the ISR with the ISR()
macro - this will produce smaller code (using less flash and RAM) and the ISRs will run faster as they don't have to check whether an interrupt is enabled for every pin on the port.
For full information and example, see the Interrupt Reference.
Like my other cores, Sketch -> Export compiled binary will generate an assembly listing in the sketch folder. A memory map is also created. The formatting of the memory map leaves something to be desired, and I've written a crude script to try to improve it, see the Export reference for more information. see Exported Files documentation
The EESAVE fuse can be controlled via the Tools -> Save EEPROM menu. If this is set to "EEPROM retained", when the board is erased during programming, the EEPROM will not be erased. If this is set to "EEPROM not retained", uploading a new sketch will clear out the EEPROM memory. Note that this only applies when programming via UPDI - programming through the bootloader never touches the EEPROM.
You must do "burn bootloader" in order to apply changes after modifying this setting, as EESAVE is on the same fuse as one the one that can be used to disable UPDI, making it an "unsafe" fuse (one that if written with the wrong options, can make the device difficult to reprogram). We don't write "unsafe" fuses like that when uploading sketches, because it should never be possible to brick your board just by uploading, which you can do without opening the tools menu and seeing that you forgot to change the options back to the intended ones for the current project.
These parts officially support BOD trigger levels of 1.8V, 2.6V, and 4.2V, with Disabled, Active, and Sampled operation options for when the chip is in ACTIVE and SLEEP modes - Disabled uses no extra power, Active uses the most, and Sampled is in the middle. As of 2.1.0, the ACTIVE/SLEEP modes have been combined into a single menu, the nonsensical options (such as using more aggressive BOD while sleeping than while awake) were removed, and the previously unexposed options were added. Sampled mode is now available with two sample rates (the faster one uses ever so slightly more power, as you would expect) and "Enabled hold wake": in that mode, BOD is disabled in sleep, enabled when not sleeping, and when waking up, code execution does not begin until the BOD is ready. See the datasheet for details on power consumption and the meaning of these options.
You must do Burn Bootloader to apply this setting. This fuse is considered "unsafe" as you can set the BOD level to a voltage higher than the highest voltage tolerated by other chips soldered to the same pcb and sharing a power rail with the AVR, and this will then prevent reprogramming without desoldering things (because you'll either be unable to program the AVR because it's in brownout reset, or if you power it at a high enough voltage to leave BOR, you would damage the afore-mentioned low voltage parts).
Between the initial header file and preliminary datasheet release, and the more recent versions of each, several BOD settings were removed from the tinyAVR 0/1-Series datasheets, and the atpack release notes described them as "unqualified" - (I understand that this has something to do with the factory testing process and possibly the vetting process for the safety critical applications these parts are certified for. ). The three official BOD levels are the voltages that the chip is guaranteed (Yup, they use that word in the datasheet!) to work at, within the manufacturer specified temperature range and running at a system clock frequency no higher than specified at that voltage. Nevertheless, the other 5 BOD levels are believed to work as one would expect (I have used them successfully), but Microchip does not provide any guarantee that they'll work, even if all other operating requirements are met, and I do not believe they are tested in production. These "not guaranteed" voltages are still supported by the megaTinyCore BOD dropdown menu, but (as of 2.0.4 - the first version that has the new headers) are marked as "(Unofficial)" in the submenu. Note that the new headers no longer provide the *_gc
enum entries for these BOD level.
| BOD level
0/1-series| BOD level
2-series | Guaranteed speed
Temperatura normal. rango | Guaranteed speed
Elevated temp. range) |-----------|------------------|---------------- --| | 1.8V | 1.8V | 5MHz | 4 MHz | | 2.1V | 2.15V | unofficial | unofficial | | 2.6V | 2.6V | 10 MHz | 8 MHz | | 2.9V | 2.95V | unofficial | unofficial | | 3.3V | 3.3V | unofficial | unofficial | | 3.7V | 3.7V | unofficial | unofficial | | 4.0V | 4.0V | unofficial | unofficial | | 4.2V | 4.3V | 20 MHz | 16 MHz |
Normal temperature range is -40-105C on 0/1-series parts and -40-85C on 2-series parts. These parts have a letter N (0/1-series) or U (2-series) at the end of the part number; this is marked on the physical chip as well on 0/1-series, but not on 2-series.
Extended temperature range is -40-125C, and these parts are denoted with the F temperature spec. The extended temperature range column applies when the temperature range is above the normal range and below 125C on F-spec parts. The normal temperature range column still applies to F-spec parts if they are running in the normal temperature range.
Most existing Arduino libraries work. See the Supported Libraries List for a more complete list and discussion of what kinds of libraries might have issues. Of the few libraries that don't work, a handful happened to also be extremely popular and heavily used, such that it was felt necessary to include a compatible version with megaTinyCore. In addition to these, libraries which expose hardware that is only present on the modern AVRs, are also included. These libraries are listed below.
This library supplies two functions to check tuning status of the chip it's running on, and now adds two software reset functions (via WDT or via software reset). It also holds the massive keywords.txt file that highlights register names and core-specific functions.
megaTinyCore helper library docs
The usual NeoPixel (WS2812) libraries, including the popular FastLED as well as AdafruitNeoPixel, have problems on these parts - they depend on hand-tuned assembly, but the execution time of several key instructions has been improved. The improvements enable significant simplification of the code for driving these LEDs. This core includes a compatible version of the tinyNeoPixel library for interfacing with these ubiquitous addressable LEDs. There are two versions, both tightly based on the Adafruit_NeoPixel library. One implements a truly identical API, differing only in name (and obviously the fact that it works on tinyAVR and Dx-Series and megaAVR 0-Series parts at clock speeds from 8 MHz to 48 MHz, instead of on most classic AVRs at 8, 12, and 16 MHz). The other version makes a slight change to the constructor and drops support for changing length at runtime, in order to realize significant flash savings (around 1k). See the tinyNeoPixel documentation and included examples for more information.
The standard EEPROM.h is available here - it works like it does on any AVR. USERSIG.h
(from "User Signature" which the datasheet has sometimes called the USERROW
) it has the same API as EEPROM, though there may be future additions to harmonize with Dx-friendly functions for updating multiple bytes. The Dx-Series parts can only erase the whole USERROW, so potentially each byte written could involve erasing and rewriting it all - the question of how to deal with that is why DxCore doesn't have a USERSIG library yet). The name "USERSIG" refers to the alternate name of the USERROW, the "User Signature" space - the name USERROW could not be used because it is defined by the io headers (it's the struct
of type USERROW_t
, made up of USERROW.USERROW0
through USERROW.USERROW31
. Not the most useful thing, but we never override the io header file definitions unless working around a bug.
Note: Prior to 2.1.0, we tried to get clever with supporting the USERROW
through the EEPROM library; that not only was shortsighted (as it's logically inconsistent on anything with more than 256b of EEPROM), it also introduced some serious bugs. Use the USERSIG.h
library for that instead.
The usual Servo library from library manager is incompatible with these parts (minor changes could make it "work", but with glaring issues and a dependence on the configuration of TCA0). This core provides a version of the Servo library which will select an appropriate timer (TCB0 is the only option on most parts, on parts with a TCB1 (2-Series and 3216, 3217, 1617, 1616 and 1614), TCB1 will be used instead, provided it's not being used for millis()
). Except on parts with a TCB1, Tone cannot be used at the same time as the Servo library. Servo output is better at higher clock speed; when using servos, it is recommended to run at the highest frequency permitted by the operating voltage, to minimize jitter.
Warning If you have installed a version of the Servo library to your /libraries folder (including via library manager), the IDE will use that version of the library (which is not compatible with these parts) instead of the one supplied with megaTinyCore (which es). As a workaround, a duplicate of the Servo library is included with a different name - to use it, just #include
instead of #include
- no other code changes are necessary.
Note that the Servo libraries were only fixed in version 2.2.0 - prior to that we had a Servo library, but it didn't work due to an astonishingly large number of bugs (I swear I tested it - apparently not well enough).
Written by @MCUDude, this provides a more accessible (much more accessible!) wrapper around the optiboot.h library (which was written by the famous @westfw) . This supports writing to the flash of any device using Optiboot, by having the application code call routines in the bootloader to write to the flash. All modern AVRs have built-in flash protection mechanisms that permit only code executing from the bootloader section ( BOOTCODE
, in their terminology) to write to the application section ( APPCODE
). While the hardware does support a third flash section ( APPDATA
) which can be written by code running in APPCODE
this is only usable if there is also a BOOTCODE
section defined (otherwise the entire flash is treated as BOOTCODE
which can never be self-programmed), and would require a separate implementation of this library to use. It would also be possible to get flash-write-from-app without use of an actual bootloader through an analog of the trick used by the DxCore Flash.h for this. Since there appears to be little demand for such a thing, that functionality is not currently implemented (they were implemented on DxCore's flash writing library because the additional effort was virtually nil, and because there was a user with a particular interest in that feature). If someone wants this, and will adapt the library, I can add the entry point to the core and give you little chunks of inline assembly that will call it. Note on terminology: on AVR Dx-Series, the fuses are called BOOTSIZE
and CODESIZE
whereas on 0/1-Series tinyAVRs they're called BOOTEND
and APPEND
. I'm not quite sure how they didn't foresee customer confusion when they called the "APPlication END" that... Regardless of the names they do the same thing, although the granularity on tinyAVRs is finer, as you would expect.
Optiboot_flasher documentation
Warning As noted above, there is a library for DxCore that is also named Flash.h
. Both allow an application to write to the flash using Optiboot if present. That is the only similarity they have . The API, NVM hardware, method used to call the bootloader, and basically everything about these libraries is different . Be sure you write code for the one that matches the hardware you're using. While I (Spence Konde) wrote the DxCore one, I don't have a particularly strong opinion about which way is "right". We made them independently, but not because we each thought the other one's idea of how it should be done was wrong. They largely reflect the way the hardware interacts with its flash. For example, the one for megaTinyCore is page-oriented with its own page buffer, and these parts write in a page-oriented manner, while the DxCore library only cares about pages when erasing - on those parts, the flash is written with word or even byte granularity!
All of these parts have at least a pair of Configurable Custom Logic (CCL) blocks; official Microchip terminology calls them "LUTs" in reference to the LookUp Table (aka truth table). We use the term "logic block" instead, to avoid confusion with other kinds of lookup table (the "lookup table" in a logic block is very different from most lookup tables; containing 8 entries, each of which is a 0 or a 1, it is a single byte, which isn't much of a table), and to prevent users who missed this paragraph from being confused by the terminology. Each block allows you to supply an arbitrary 3-input truth table, as well as configuring additional options like a synchronizer, filter, or edge detector. The CCL operates asynchronously (unless you using the synchronizer) - meaning that things can happen faster than the clock speed. Thesynchronizer that will synchronize the CCL output to one of several clock sources (probably the system clock will be what you would synchronize with). The inputs can come from pins, events, or other peripherals. There's a feedback input as well, which allows a great many exciting possibilities, and a "sequencer" that can act like a latch or flip-flop using the outputs of a pair of logic blocks as its inputs. This is an incredibly powerful peripheral - especially on the 2-Series parts, which have a second pair of logic blocks, as well as the capability to trigger an interrupt when the state of one changes.
The Logic ( #include Logic.h
) library provides a simple wrapper around the CCL hardware in the tinyAVR 0/1/2-Series devices. This library is also included in DxCore and MegaCoreX, covering all AVRs with CCL hardware. Written by @MCUDude.
Logic library documentation
These parts have either 1 (everything else) or 3 (1614, 1616, 1617, 3216, and 3217) on-chip analog comparators which can be used to compare two analog voltages, and, depending on which is larger, do one or more of the following: generate an event output, control an output pin, or fire an interrupt. One of the voltages can be the internal reference (0-Series) or an internal reference scaled by an 8-bit DAC (everything else). This library, written by @MCUDude, provides a simple wrapper around the analog comparator(s) which makes their configuration easier and resulting code more readable (also easier on the wrists - less stuff to type in all caps) than manually configuring registers, while exposing nearly the full featureset of the analog comparators on these parts. Do note does not support the Window Comparator option for the parts with 3 comparators; There doesn't exactly seem to be a lot of demand for that one, though!
The Comparator library ( #include Comparator.h
) is also included in DxCore and MegaCoreX, covering all modern AVRs with comparator hardware. Written by @MCUDude.
Comparator library documentation
In general you should expect the following about library compatibility:
__AVR_ARCH__ >= 102
.architectures=*
would suggest that it would work anywhere - all this means is that there are not separate folders with implementations for different architectures. It does not mean that the library does not make assumptions about architecture, test against architecture specific stuff with #ifdef
s and so on. Unfortunately, library authors often use this when they know it works with a couple of architectures, shrug their shoulders and assume it'll work anywhere and put down a * in that field.The amount of effort required to port a given library will vary widely depending on the library. Some are straightforward for anyone reasonably familiar with these parts and what to generally expect and approach it. Any library associated with some peripheral that both classic and modern had, it's probably going to be a straightforward change if you just need to swap out the classic peripheral for the modern one - Yes, every bitfield will be named differently, but only rarely did a modern AVR's peripheral lack a feature the classic version had. The USART on classic AVR has whack stuff like MPCM, and the 9 bit mode - sorry, modes. Even the layout of some of the registers is similar - the parts aren't as different as they appear at first. Another type is the "bitbanger", where they're using direct port writes; the solution to this is cookbook - switch to using the relevant PORT or VPORT registers. Input capture is a little more complicated because you have to set up the event channel, and figure out how to offer that in a library (that is the hard part). But the consistent factor is that generally, none of these things are long slow painful slogs. And as noted above, many libraries will work out of the box, or have already been adapted.
The fact that many libraries can be ported no or little underlines the need for reports from users about incompatible libraries as well as compatible ones not listed on the table linked below. Usually reports of non-working libraries to add to the table result in the library getting fixed , and the fixed library being added to the table; Almost all of the fruit here low hanging. So when you come upon incompatible libraries report it to me! Many libraries that were initially incompatible were fixed up in under 10 minutes. Porting typical libraries from classic AVRs requires a fraction of the effort that the "tar pit" libraries included with this core take to port to new modern AVR families (these are Comparator, Logic, Event: Logic and Event are both, on their own, large, complicated, "system-like" peripherals. The CCL is just complex in general, and has seen relatively modest changest between families, except for the t0/1. Event is simple in theory and much more complicated in practice, in no small part because the implementation on the 0-series, 1-series, mega0, 2-series/DA/DB/DD, EA and the EB are each different. And a single library has to support all of them with a consistent interface and paper over all the differences.
I know lots of people use libraries that aren't on that list, and I fully expect that there is a great number of libraries that work and are not listed, and I'd love to hear about them. Use the "discussions" or email me, or even submit a PR to add a line to the table. I want to hear about working libraries so others will know they work and not hesitate, and I'm even more interested in ones that don't work so they can be fixed - or determined to be unfixable)
For more information on resetting from software, using the Watchdog Timer, the causes of unexpected resets and how to prevent them, and generally all things reset-related, see the Reset Guide.
It is often useful to identify what options are selected on the menus from within the sketch; this is particularly useful for verifying that you have selected the options you wrote the sketch for when opened later by yourself or someone who you shared it with. Or, you can use such in-sketch identification, combined with preprocessor #if
macros, to select the appropriate code depending on the part or options at hand.
There are a great number of #define
s provided to get information about the hardware in-use, in order to write portable and flexible code in your sketch or, especially, library code.
Note : You cannot distinguish an extended temperature range part from a normal one from software. For 0/1-series, most packages mark the temperature grade. this is no longer true on the 2-series, nor on any part released after the 1-series - So better make sure you mark those parts if you unpack them, because the only alternative is to give the lot number to Microchip support, and they'll tell you if it's an F, a U, or an N (FUN letters - but notice that you can't turn any letter into any other letter without both erasing and adding lines. The same is true of the different set of letters they used on automotive parts - BMZ or something - less FUN, but they had the same "modification resistance" (hey, on at least one occasion, a quantity of t13'd had the markings polished off and were remarked as tiny85's and sold as such on aliexpress and ebay - that was worth doing to some criminal in China! Unethical behavior is of course the norm for companies everywhere, but in the US, criminality of the company (as opposed to rogue employees) is not pervasive. When it rises above that, low end of chinese industry - ex, virtually all PVC wire is 2-8 AWG smaller than what is printed on the wire; same with silicone wire (but FEP insulated wire is always spot on, cause it's not at the low end ya see), one has to assume that (well, if they still marked the parts) someone has taken a bunch of parts marked I (vertical line), added 3 horizontal lines to each one (One imagines, with the same sort of automated chip marking method that would be used for putting any other pattern, except here it would just be the missing parts of an E. The consistency of the location of markings on packages is remarkably consistent specimen to specimen, such that you might be able to target by position and get it close enough to be convincing, and with just 3 small marks and no grinding, and significant price difference between I and E spec parts for certain parts (oddly , not for most tinies). Of course when they adopted the I and E when they stopped marking parts at all, so this is academic. But can you seriously imagine anyone inspecting 200 boards and writing down every lot number he saw, and emailing the lista para Microchip and asking for confirmation that they're all E's as he ordered?).
A new version of Optiboot (Optiboot_x) now runs on the tinyAVR 0-Series, 1-Series and 2-Series chips. It's under 512 bytes, and works on all parts supported by this core, allowing for a convenient workflow with the same serial connections used for both uploading code and debugging (like a normal Arduino Pro Mini). Note the exception about not having autoreset unless you disable UPDI (except for the 20 and 24-pin 2-Series parts which can put reset on PB4 instead), which is a bit of a bummer.
To use the serial bootloader, select a board definition with (optiboot) after it. Note - the optiboot suffix might be visually cut off due to the width of the menu; the second / lower set of board definitions in the board menu are the optiboot ones). The 2-Series Optiboot definitions and the 0/1-Series Optiboot definitions are separate entries in the board menu.
See the Optiboot referencefor more information.
These guides cover subsystems of the core in much greater detail (some of it extraneous or excessive).
Covering top-level functions and macros that are non-standard, or are standard but poorly documented, and which aren't covered anywhere else.
The API reference for the analog-related functionality that is included in this core beyond the standard Arduino API.
The API reference for the digital I/O-related functionality that is included in this core, beyond the standard Arduino API, as well as a few digital I/O-related features that exist in the hardware which we provide no wrapper around.
Documents the (largely intended for internal use) dirty inline assembly macros that are used by the core to improve performance or reduce code size.
Includes a list of all interrupt vectors that can be used, how the flags are cleared (not a substitute for the datasheet - just a very quick reminder), which parts each vector exists on, and and what parts of the core, if any, make use of a vector. It also has general guidance and warnings relating to interrupts their handling, including estimates of real-world interrupt response times.
The USARTs (Serial) have some greatly enhanced functionality compared to the stock core.
Serial UPDI is our recommended tool for UPDI programming.
Supported clock sources and considerations for the use thereof.
Manufacturer specs for speed at various voltages, and some discussion of BOD thresholds - this is written largely from a very conservative perspective, in contrast to most of the documentation.
These are provided by the core and can be overridden with code to run in the event of certain conditions, or at certain times in the startup process.
The core feature #define
s are used by megaTinyCore and other cores I maintain as well. This also documents what constant values are defined by the core for version identification, testing for features, and dealing with compatibility problems.
Export compiled binary generates both assembly listings and memory maps, in addition to the hex file. The options selected are encoded in the name of the file to help prevent confusion and make it easy to compare two configurations when you are surprised by the differences between them. Also provides links to a script I wrote to reformate memory maps so you can read the damned things.
The sources of reset, and how to handle reset cause flags to ensure clean resets and proper functioning in adverse events. Must read for production systems
The installation and operation of the Optiboot bootloader (for uploading over straight serial (not SerialUPDI)) is described here. Not recommended except on the 20/24-pin 2-Series (since they have the alt reset pin) or for special use cases that demand it.
This contains detailed information on how the timers are used in megaTinyCore, and some background on their capabilities.
These guides are older; some are still relevant.
This has been recently updated and will likely be turned into a Ref_TCA0.
This document describes how (on the 0 and 1 Series only) the ADC can be taken over and reconfigured, with particular attention to free running mode. The 2-Series ADC is different, and it would require changes to reflect those differences.
A delightful, though unfortunately short, document on bare metal programming in C.
The bible of the AVR instruction set. Like any such tome, it is a lengthy document which contains timeless wisdom from the creator(s), written in obtuse and challenging language and a confusing syntax (though you won't go to hell if you don't read it, if you're writing assembly without it, you might not be able to tell the difference).
As promised, a bunch of additional information was released; Unfortunately it leaves some of the key questions unanswered.
printf()
implementation - The default option can be swapped for a lighter weight version that omits most functionality to save a tiny amount of flash, or for a full implementation (which allows printing floats with it) at the cost of about 1k extra flash. Note that if non-default options are selected, the implementation is always included in the binary, and will take space even if not called. This applies everywhere that format strings are used, including Serial.printf()
.attachPortAEnable()
and replace A
with the letter of the port) before attaching the interrupt. This allows attachInterrupt()
to be used without precluding any use of a manually defined interrupt (which is always much faster to respond). Basically any time you "attach" an interrupt, the performance is much worse.millis()
, micros()
and pulseInLong()
will be available. If set to disable, these will not be available, Serial methods which take a timeout as an argument will not have an accurate timeout (though the actual time will be proportional to the timeout supplied); delay()
will still work. Disabling millis()
and micros()
saves flash, and eliminates the millis()
interrupt every 1-2 ms; this is especially useful on the 8-pin parts which are extremely limited in flash. Depending on the part, options to force millis()
/ micros()
onto specific timers are available. A #error
will be shown upon compile if a specific timer is chosen but that timer does not exist on the part in question (as the 0-Series parts have fewer timers, but run from the same variant). If RTC is selected, micros()
and pulseInLong()
will not be available - only millis()
will be.There are however a few cautions warranted regarding megaTinyCore - either areas where the core is different from official cores, or where the behavior is the same, but not as well known.
If you are manually manipulating registers controlling a peripheral, except as specifically noted in relevant reference pages, the stated behavior of API functions can no longer be assured. It may work like you hope, it may not, and it is not a bug if it does not, and you should not assume that calling said API functions will not adversely impact the rest of your application. For example, if you "take over" TCA0, you should not expect that using analogWrite()
- except on the two pins on the 20/24-pin parts controlled by TCD0 - will work for generating PWM. If you reconfigure TCA0 except as noted in Ref_Timers, without calling takeOverTCA0
, both analogWrite()
and digitalWrite()
on a PWM pin may disrupt your changed configuration.
While we generally make an effort to emulate the official Arduino core, there are a few cases where the decision was made to have different behavior to avoid compromising the overall functionality; the official core is disappointing on many levels. The following is a (hopefully nearly complete) list of these cases.
Earlier versions of megaTinyCore, and possibly very early versions of DxCore enabled the internal pullup resistors on the I2C pins. This is no longer done automatically - they are not strong enough to meet the I2C specifications, and it is preferable for it to fail consistently without external ones than to work under simple conditions with the internal ones, yet fail under more demanding ones (more devices, longer wires, etc). However, as a testing aid, we supply Wire. usePullups()
to turn on the weak internal pullups. If usePullups()
ever fixes anything, you should install external pullups straight away. Our position is that whenever external pullups are not present, I2C is not expected to work. Remember that many modules include their own on-board pullups. For more information, including on the appropriate values for pullups, see the Wire library documentation
The official core for the (similar) megaAVR 0-Series parts, which megaTinyCore was based on, fiddles with the interrupt priority (bet you didn't know that!) in methods that are of dubious wisdoom. megaTinyCore does not do this, saving several hundred bytes of flash in the process, and fixing at least one serious bug which could result in the microcontroller hanging if Serial was used in ways that everyone tells you not to use it, but which frequently work anyway . Writing to Serial when its buffer is full, or calling Serial.flush()
with interrupts disabled, or during another ISR (which you really shouldn't do ) will behave as it does on classic AVRs and simply block, manually calling the transmit handlers, until there is space in the buffer for all of the data waiting to be written or the buffer is empty (for flush()
). On th stock megaAVR core, this could hang forever.
This is deprecated on the official core and is, and always has been, a dreadful misfeature. Dropped as of 2.3.0.
digitalRead()
Does Not Turn Off PWM On official cores, and most third party ones, the digitalRead()
function turns off PWM when called on a pin. This behavior is not documented by the Arduino reference. This interferes with certain optimizations, makes digitalRead()
take at least twice as long (likely much longer) as it needs to and generally makes little sense. Why should a "read" operation change the thing it's called on? We have a function that alters the pin it's called on: digitalWrite()
. There does not seem to be a logically coherent reason for this and, insofar as Arduino is supposed to be an educational platform it makes simple demonstrations of what PWM is non-trivial (imagine setting a pin to output PWM, and then looking at the output by repeatedly reading the pin).
digitalWrite()
and INPUT
Pins Like the official "megaavr" core, calling digitalWrite()
on a pin currently set INPUT
will enable or disable the pullups as appropriate. digitalWrite()
also supports "CHANGE" as an option; on the official core, this will turn the pullup on, regardless of which state the pin was previously in, instead of toggling the state of it. The state of the pullup is now set to match the value that the port output register was just set to.
This was done because of the huge volume of code that makes use of this behavior. We experimented with making pinMode() do the inverse for INPUT and INPUT_PULLUP, but this was removed by unanimous agreement by everyone in the discussion thread.
analogWrite()
and TCD0 Pins Please see the above PWM feature description if using PWM on those pins and also using digitalRead()
or direct port writes on the same pins (PIN_PC0, and PIN_PC1).
On the official "megaavr" board package, TCA0 is configured for "single mode" as a three-channel 16-bit timer (used to output 8-bit PWM). megaTinyCore always configures it for "Split mode" to get additional PWM outputs. See the datasheets for more information on the capabilities of TCA0. See Taking over TCA0 for information on reconfiguring it. One downside to this is that the compare channels do not support buffering, so changing the duty cycle can cause a glitch lasting up to one PWM cycle (generally under 1 ms).
0 is a count, so at 255, there are 256 steps, and 255 of those will generate PWM output - but since Arduino defines 0 as always off and 255 as always on, there are only 254 possible values that it will use. The result of this is that (I don't remember which) either analogWrite(pin,254)
results in it being LOW
2/256's of the time, or analogWrite(pin,1)
results in it being HIGH
2/256's of the tiempo. On megaTinyCore, with 255 steps, 254 of which generate PWM, the hardware is configured to match the API, and this does not occur. As it happens, 255 also (mathematically) works out such that integer math gets exact results for millis()
timing with both 16-MHz-derived and 20-MHz-derived clock speeds, which is relevant when TCA0 is used for millis()
momento. The same thing is done for TCD0, though to 509, giving 510 steps. analogWrite()
accounts for this, so that we can get the same output frequency while keeping the fastest synchronization prescaler for fastest synchronization between TCD0 and system clock domains.
On the official "megaavr" board package, as well as DxCore, the Type B timers are used to generate 8-bit PWM (one pin per timer). There are very few circumstances where this could increase the number of usable PWM pins. These timers are just too scarce and valuable on these parts. Being minimally useful for PWM, in short supply, and highly desirable for other purposes, support for using Type B timers for PWM was removed in order to save space that would otherwise be used initializing these timers for PWM and handling them in analogWrite()
et . Alabama. If a Type B timer is used for millis()
, it is configured in a radically different way than the official core does it.
They return and expect uint8_t
(byte) values, not enum
s like the official megaavr board package does. Like classic AVR cores, constants like LOW
, HIGH
, etc are simply #define
d to appropriate values. The use of enum
s unfortunately broke many common Arduino programming idioms and existing code (granted, these idioms were poor programming practice - they're also incredibly widespread and convenient), increased flash usage, lowered performance and made optimization more challenging. The enum
implementation made language design purists comfortable and provided error checking for newbies, because you couldn't pass anything that wasn't a PinState to a digital I/O function and would see that error if you accidentally got careless. Nevertheless, due to all the complaints, a compatibility layer was added to the official core, so all the old tricks would work again, it was just less performant. However, that got rid of what was probably the most compelling benefit by allowing the workarounds: the fact that it did generate an error for new users to train them away from common Arduino practices like passing 1 or 0 to digitalWrite()
, if(digitalRead(pin))
and the like. The choice of names of the enum
s also had the perverse effect of making PinMode(pin,OUTPUT)
(an obvious typo of pinMode(pin,OUTPUT)
) into valid syntax (comma operator turns pin,OUTPUT
into OUTPUT
, and it returns a new PinMode
of value OUTPUT
...) and does nothing with it, instead of a syntax error (It took me over an hour to find the erroneous capitalization. That evening, I converted the digital I/O functions to the old signatures and removed the enum
s). Anyway - the enum
s are not present here, and they never will be; this is the case with MegaCoreX and DxCore as well.
There are two classes of significant low level architectural differences (aside from the vastly improved peripherals): the improved instruction set and the unified memory address space.
The classic AVR devices all use the venerable AVRe
(ATtiny) or AVRe+
(ATmega) instruction set ( AVRe+
differs from AVRe
in that it has hardware multiplication and supports devices with more than 64k of flash). Modern AVR devices (with the exception of ones with minuscule flash and memory, such as the ATtiny10, which use the reduced core AVRrc
) all use the latest iteration of the AVR instruction set, AVRxt
. AVRxt
has much in common with AVRxm
(used in XMega parts) in terms of instruction timing - and in the few places where they differ, AVRxt
is faster (SBIC, as well as LDD, and LD with pre-decrement, are all 1 clock slower on AVRxm
vs AVRxt
or AVRe
), however AVRxt
doesn't have the single-instruction-two-clock read-and-write instructions for memory access LAT
, LAC
, LAS
, and XCH
. The difference between subspecies of the AVR instruction set is unimportant for 99.9% of users - but if you happen to be working with hand-tuned assembly (or are using a library that does so, and are wondering why the timing is messed up), the changes are:
As you can see, everything that involves writing to the SRAM is faster now; it would appear that any time it is writing to a location based on one of the pointer registers or the stack pointer, it's a single cycle. All the other improvements except CBI
and SBI
can be viewed as a consequence of that. Of course, the variants of CALL
are faster; they have to put the return address into the stack. I can't say I've ever felt like LAT
, LAC
, or LAS
would be terribly useful as they are described in the instruction set manual - those take a register and the address pointed to by the Z register, load the contents of the specified address and toggle, set or clear in that memory address the bits that were set to begin with in the register. If that worked on special function registers, it would be a very useful instruction, taking PERIPHERAL.REGISTER |= SOME_BIT_bm;
from a 5 clock, non-atomic operation to a 2 clock atomic one! But it says they only work on SRAM... so not as much of a loss. XCH
is more obviously useful than the others, but all 4 of them come with the need to set up the Z register... which in many cases would take long enough that it wouldn't be a notable improvement.
Note that the improvement to PUSH
can make interrupts respond significantly faster (since they have to push the contents of registers onto the stack at the beginning of the ISR), though the corresponding POP
s at the end aren't any faster. The change with ST
impacted tinyNeoPixel. Prior to my realizing this, the library worked on SK6812 LEDs (which happened to be what I tested with) at 16/20 MHz, but not real WS2812's. However, once I discovered this, I was able to leverage it to use a single tinyNeoPixel library instead of a different one for each port like was needed with ATTinyCore (for 8 MHz, they need to use the single cycle OUT
on classic AVRs to meet timing requirements, the two cycle ST
was just too slow; hence the port had to be known at compile time, or there must be one copy of the routine for each port, an extravagance that the ATtiny parts cannot afford. But with single cycle ST
, that issue vanished).
Oh, and one other instruction it doesn't have that (some) AVRxm parts have: The hardware DES
encryption instruction - an instruction which is most effective at marking AVRxm as, ah, back from the time when DES
was a big deal.
On all modern AVRs with up to 48k of flash, both the flash and ram reside in the same address space - On tinyAVRs, the program memory starts at 0x8000, while on megaAVR 0-Series, it starts at 0x4000 to leave room for the 48k of flash that they can have, and on the Dx-Series parts with up to 32k of flash, they have the same layout as the tinyAVRs, while Dx-Series parts with 64k or 128k of flash have a 32k section of flash mapped at any given time (how to make sure variables go into this memory mapped flash has been described elsewhere in this document). There is another big and fundamental change to the layout of the address space as well: the registers are organized by peripheral. PORTA is assigned 0x400 to 0x41F. PORTB is the next 32 bytes, and so on - and the address space is far sparser - all the peripherals have multiple "reserved" registers that may or may not get functions added in the future. And each instance of a peripheral on a part that has multiple of them has the same layout. You can, say, pass a pointer to a TCB around without the functions that get it knowing which TCB they'll get, and then access the TCB registers through it. On classic AVRs the names of the registers were consistent, but their locations were all over the place, packed much more tightly, so that sort of trick isn't possible. This also means that the EEPROM (and USERROW) are part of this unified address space (on classic AVRs, reading was accomplished through special function registers, and was far more awkward).
The lowest 64 registers are special - you can read or write them with the IN
or OUT
instructions (hence, "I/O space") in a single clock cycle, without setting up a pointer to them as you would need to with ST
or LD
. The 32 "Low I/O registers" additionally have bit-level access instructions CBI
and SBI
to clear and set bits, and SBIC
/ SBIS
to skip the next instruction if a certain bit is set or cleared. On all AVRxt parts released so far, the low I/O registers are used only for the VPORTs, up to VPORTG or the last port on the part, whichever comes first. This means VPORTG.OUT |= 1 << n
, where n is known at compile-time and constant , is a 1 clock cycle atomic operation , while VPORTG.OUT = 1 << n
(note the =
in lieu of |=
) takes two clock cycles. For the latter, the first cycle is to put the value to be stored into a register, and the second is to write it with an OUT
instruction. The GPIOR0-3 registers occupying the last 4 bytes in the low I/O space (those are user-defined registers to use as you choose. We use GPIOR0 internally during startup to record reset cause, and store two types of warnings applicable to tuning ). The reset flag register is always cleared very early in startup to prevent dirty resets, and when using a bootloader, so that it can honor bootloader entry conditions on next reset). No other part of this core touches those registers, and we only set GPIOR0; we never read it. So all can be used freely, as long as you remember that GPIOR0 is not empty when you enter setup, and contains the reset cause flags. Other Low I/O registers are not used by the hardware.
The 32 "high I/O registers" are used even less - they only contain the the stack pointer, RAMPZ
on the 128k DA/DB parts, SREG
, and CCP
(Configuration Change Protection - where _PROTECTED_WRITE()
does it's magic to let you write to protected registers. That's all - 5 out of 32 registers are used, the rest are "reserved". On classic AVRs, registers for assorted peripherals that the designers thought would be accessed often were put into the I/O space, so it was a disappointment that they didn't put an alias of any other registers there. I'd vote for the intflags registers to be aliased there
megaTinyCore itself is released under the LGPL 2.1. It may be used, modified, and distributed freely, and it may be used as part of an application which, itself, is not open source (though any modifications to these libraries must be released under the LGPL as well). Unlike LGPLv3, if this is used in a commercial product, you are not required to provide means for users to update it.
The DxCore hardware package (and by extension this repository) contains DxCore as well as libraries, bootloaders, and tools. These are released under the same license, unless specified otherwise . For example, tinyNeoPixel and tinyNeoPixel_Static, being based on Adafruit's library, are released under GPLv3, as described in the LICENSE.md in those subfolders and within the body of the library files themselves.
The pyupdi-style serial uploader in megaavr/tools is a substantially renovated version of pymcuprog from Microchip, which is not open source has now been released under the open source MIT license! .
Any third party tools or libraries installed on behalf of megaTinyCoreCore when installed via board manager (including but not limited to, for example, avr-gcc and avrdude) are covered by different licenses as described in their respective license files.