Manejo de actualizaciones de registro en sistemas Modbus

4

Actualmente estoy desarrollando un sistema habilitado para Modbus RTU que consta de DSP y un microprocesador que maneja las comunicaciones Modbus. El DSP está enviando datos al microprocesador y el microprocesador proporciona una interfaz Modbus a los resultados del DSP. Los resultados pueden actualizarse en cualquier momento (algunos se actualizan periódicamente y otros se actualizan a intervalos aleatorios).

Si el host Modbus decide sondear un conjunto de registros que corresponden a un solo conjunto de datos en varios comandos Modbus (tuvimos una experiencia con un host Modbus que no pudo recuperar más de 32 registros a la vez) existe la posibilidad que los datos se actualizarán entre las encuestas de Modbus.

¿Hay alguna forma convencional de manejar escenarios como los de los sistemas Modbus?

    
pregunta udushu

2 respuestas

4

Parece que tiene un bloque de registros que se deben leer o escribir de forma atómica (es decir, leerlos o escribirlos todos o leerlos / escribirlos ninguno). Tradicionalmente, cómo lidiar con esto es tener un conjunto de registros sombra; el ISR llena o usa una tabla, y las subrutinas UART usan otra. Las rutinas que actualizan las estructuras de datos bloquean el conjunto de trabajo para que otras rutinas no obtengan una actualización parcial. Las rutinas que deben acceder a las tablas comprueban el bloqueo y "saltan su turno" o esperan a que se libere el bloqueo.

Usted hace estas "secciones críticas" (secciones donde no se permite acceder a la tabla) lo más rápido posible, por lo que recomendé un "conjunto de sombras" para las rutinas de UART ya que probablemente sean las cosas más lentas para acceder a las tablas y, de hecho, pueden ser las únicas rutinas que deben acceder a todo el conjunto como una sola unidad. No bloquee la tabla hasta que esté absolutamente seguro de que necesita hacerlo, y luego la bloquea solo durante el tiempo necesario para copiar los datos.

Algo como esto:

if (command_is_good && cmd_is_request) {
    lock_working_table();
    memcpy(serial_copy, working_copy, sizeof(*working_copy);
    unlock_working_table();
    prepare_response(serial_copy);
}

if (command_is_good && cmd_is_update) {
    if (verify_table(serial_copy)) {
        lock_working_table();
        memcpy(working_copy, serial_copy, sizeof(*working_copy));
        unlock_working_table();
        prepare_response();
     }
}

Puede obtener resultados similares al deshabilitar la interrupción de ADC, pero a lo largo de los años he encontrado que, en general, hay muy, muy pocas veces las que desea atornillar con la función de interrupción, y esto casi nunca es una de ellas. El bloqueo y un mejor diseño son casi siempre la forma correcta de manejar esto, por lo que agregué el comentario a la publicación de @kvegaoro. Se confunde con su tiempo, que puede o no ser importante, y si deshabilita el ISR de UART podría desbordar su FIFO.

Si encuentra que tiene un gran conjunto de registros que deben actualizarse de forma atómica, es posible que también desee dividirlos en grupos atómicos más pequeños y limitar su tamaño o límites de solicitud.

Editar para abordar el comentario de @ DaveTweed:

En cuanto a una convención utilizada por los dispositivos ModBus ... Lo mejor de ModBus es también lo peor de ModBus; Eres libre de hacer las cosas como quieras. La especificación es muy "floja" a ese respecto. No hay ninguna convención que yo sepa, pero los dispositivos ModBus que tienen tal requisito sobre bloques de registros tendrían que implementar cosas similares a como describí la solución anterior. Casi todos los dispositivos triviales lo limitan a un solo registro para operaciones de lectura / escritura, evitando cuidadosamente el problema. :-)

    
respondido por el akohlsmith
0

En los sistemas en los que he trabajado con Datos provenientes de DSP o ADC externo de alta precisión, generalmente se controla mediante interrupciones (también supongo que su sistema está controlado por interrupciones, ya que dice que los datos pueden ingresar en cualquier momento). Por lo general, cuando recibe una consulta Modbus, es posible que desee desactivar las interrupciones momentáneamente mientras maneja la consulta y habilite las interrupciones nuevamente después de que la consulta haya sido manejada. Una vez que habilite las interrupciones, se manejarán todas las solicitudes de interrupción pendientes. De esta manera, se asegura de que los valores no se actualicen en medio de una consulta y terminen con los resultados incorrectos. Espero que esto ayude

    
respondido por el Kvegaoro

Lea otras preguntas en las etiquetas